From ae17e7e9a272b422176962d896e387496b1806e8 Mon Sep 17 00:00:00 2001 From: Vadym Matsishevskyi <25311427+vam-google@users.noreply.github.com> Date: Sun, 23 May 2021 23:53:34 -0700 Subject: [PATCH] chore: DIREGAPIC #2 refactoring of the rest Composer Classes (#730) --- .github/workflows/ci.yaml | 2 +- CHANGELOG.md | 7 + dependencies.properties | 3 +- .../gapic/composer/ClassComposer.java | 18 - .../generator/gapic/composer/Composer.java | 8 + .../composer/comment/StubCommentComposer.java | 16 - ...tServiceCallableFactoryClassComposer.java} | 169 +-- ...bstractServiceClientTestClassComposer.java | 969 +++++++++++++++++ .../AbstractServiceSettingsClassComposer.java | 31 +- .../AbstractServiceStubClassComposer.java} | 514 +++------- ...ractServiceStubSettingsClassComposer.java} | 179 +--- .../gapic/composer/common/BUILD.bazel | 5 +- .../BatchingDescriptorComposer.java | 2 +- .../gapic/composer/common/ClassComposer.java | 1 - .../{ => common}/RetrySettingsComposer.java | 2 +- .../ServiceClientClassComposer.java | 2 +- .../ServiceStubClassComposer.java | 2 +- .../common}/TransportContext.java | 24 +- .../gapic/composer/grpc/GrpcContext.java | 6 +- ...pcServiceCallableFactoryClassComposer.java | 179 ++++ .../grpc/GrpcServiceStubClassComposer.java | 362 +++++++ .../{ => grpc}/MockServiceClassComposer.java | 3 +- .../MockServiceImplClassComposer.java | 3 +- .../ServiceClientTestClassComposer.java | 970 ++---------------- .../grpc/ServiceSettingsClassComposer.java | 4 + .../ServiceStubSettingsClassComposer.java | 182 ++++ .../gapic/composer/utils/ClassNames.java | 19 - .../generator/gapic/model/GapicContext.java | 4 +- .../api/generator/gapic/model/Transport.java | 33 + .../gapic/protoparser/HttpRuleParser.java | 29 +- .../generator/gapic/protoparser/Parser.java | 88 +- .../api/generator/gapic/composer/BUILD.bazel | 24 +- .../gapic/composer/ComposerTest.java | 3 +- .../gapic/composer/TestProtoLoaderUtil.java | 45 - .../gapic/composer/common/BUILD.bazel | 6 + .../BatchingDescriptorComposerTest.java | 15 +- .../RetrySettingsComposerTest.java | 31 +- .../ServiceClientClassComposerTest.java | 15 +- .../ServiceStubClassComposerTest.java | 11 +- .../composer/common/TestProtoLoader.java | 23 +- .../gapic/composer/common/goldens/BUILD.bazel | 6 + ...DescriptorComposerTestNoSubresponse.golden | 0 ...ngDescriptorComposerTestSubresponse.golden | 0 .../goldens/DeprecatedServiceClient.golden | 0 .../goldens/DeprecatedServiceStub.golden | 0 .../{ => common}/goldens/EchoClient.golden | 0 .../{ => common}/goldens/EchoStub.golden | 0 .../goldens/IdentityClient.golden | 0 .../gapic/composer/constants/BUILD.bazel | 13 - .../composer/constants/ComposerConstants.java | 22 - .../DeprecatedServiceClientTest.golden | 234 ----- .../generator/gapic/composer/grpc/BUILD.bazel | 7 + ...rviceCallableFactoryClassComposerTest.java | 11 +- .../GrpcServiceStubClassComposerTest.java | 19 +- .../composer/grpc/GrpcTestProtoLoader.java | 5 +- .../MockServiceClassComposerTest.java | 11 +- .../MockServiceImplClassComposerTest.java | 11 +- .../ServiceClientTestClassComposerTest.java | 26 +- .../ServiceStubSettingsClassComposerTest.java | 29 +- .../DeprecatedServiceClientTest.golden | 130 +++ .../DeprecatedServiceStubSettings.golden | 0 .../{ => grpc}/goldens/EchoClientTest.golden | 2 +- .../goldens/EchoStubSettings.golden | 0 ...rpcDeprecatedServiceCallableFactory.golden | 0 .../goldens/GrpcDeprecatedServiceStub.golden | 0 .../goldens/GrpcEchoCallableFactory.golden | 0 .../{ => grpc}/goldens/GrpcEchoStub.golden | 0 .../goldens/GrpcPublisherStub.golden | 0 .../{ => grpc}/goldens/GrpcTestingStub.golden | 0 .../goldens/LoggingClientTest.golden | 2 +- .../LoggingServiceV2StubSettings.golden | 0 .../goldens/MockDeprecatedService.golden | 0 .../goldens/MockDeprecatedServiceImpl.golden | 0 .../{ => grpc}/goldens/MockEcho.golden | 0 .../{ => grpc}/goldens/MockEchoImpl.golden | 0 .../goldens/PublisherStubSettings.golden | 0 .../goldens/SubscriberClientTest.golden | 2 +- .../goldens/TestingClientTest.golden | 2 +- .../gapic/composer/resourcename/BUILD.bazel | 69 +- .../ResourceNameHelperClassComposerTest.java | 11 +- .../goldens/AgentName.golden | 0 .../composer/resourcename/goldens/BUILD.bazel | 6 + .../goldens/BillingAccountLocationName.golden | 0 .../goldens/FoobarName.golden | 0 .../goldens/SessionName.golden | 0 .../goldens/TestName.golden | 0 .../apis/kms/v1/cloudkms_test_mixins_v1.yaml | 37 +- .../kms/v1/KeyManagementServiceClient.java | 67 +- .../v1/KeyManagementServiceClientTest.java | 54 +- .../kms/v1/KeyManagementServiceSettings.java | 11 - .../google/cloud/kms/v1/gapic_metadata.json | 3 - .../v1/stub/GrpcKeyManagementServiceStub.java | 34 +- .../kms/v1/stub/KeyManagementServiceStub.java | 5 - .../KeyManagementServiceStubSettings.java | 23 - .../com/google/iam/v1/MockIAMPolicyImpl.java | 20 - version.txt | 2 +- 96 files changed, 2504 insertions(+), 2379 deletions(-) delete mode 100644 src/main/java/com/google/api/generator/gapic/composer/ClassComposer.java rename src/main/java/com/google/api/generator/gapic/composer/{GrpcServiceCallableFactoryClassComposer.java => common/AbstractServiceCallableFactoryClassComposer.java} (57%) create mode 100644 src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java rename src/main/java/com/google/api/generator/gapic/composer/{GrpcServiceStubClassComposer.java => common/AbstractServiceStubClassComposer.java} (67%) rename src/main/java/com/google/api/generator/gapic/composer/{ServiceStubSettingsClassComposer.java => common/AbstractServiceStubSettingsClassComposer.java} (92%) rename src/main/java/com/google/api/generator/gapic/composer/{ => common}/BatchingDescriptorComposer.java (99%) rename src/main/java/com/google/api/generator/gapic/composer/{ => common}/RetrySettingsComposer.java (99%) rename src/main/java/com/google/api/generator/gapic/composer/{ => common}/ServiceClientClassComposer.java (99%) rename src/main/java/com/google/api/generator/gapic/composer/{ => common}/ServiceStubClassComposer.java (99%) rename src/main/java/com/google/api/generator/gapic/{model => composer/common}/TransportContext.java (88%) create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java rename src/main/java/com/google/api/generator/gapic/composer/{ => grpc}/MockServiceClassComposer.java (98%) rename src/main/java/com/google/api/generator/gapic/composer/{ => grpc}/MockServiceImplClassComposer.java (99%) rename src/main/java/com/google/api/generator/gapic/composer/{ => grpc}/ServiceClientTestClassComposer.java (53%) create mode 100644 src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java create mode 100644 src/main/java/com/google/api/generator/gapic/model/Transport.java delete mode 100644 src/test/java/com/google/api/generator/gapic/composer/TestProtoLoaderUtil.java rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/BatchingDescriptorComposerTest.java (92%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/RetrySettingsComposerTest.java (94%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/ServiceClientClassComposerTest.java (80%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/ServiceStubClassComposerTest.java (81%) create mode 100644 src/test/java/com/google/api/generator/gapic/composer/common/goldens/BUILD.bazel rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/BatchingDescriptorComposerTestNoSubresponse.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/BatchingDescriptorComposerTestSubresponse.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/DeprecatedServiceClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/DeprecatedServiceStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/EchoClient.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/EchoStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => common}/goldens/IdentityClient.golden (100%) delete mode 100644 src/test/java/com/google/api/generator/gapic/composer/constants/ComposerConstants.java delete mode 100644 src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClientTest.golden rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/GrpcServiceCallableFactoryClassComposerTest.java (82%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/GrpcServiceStubClassComposerTest.java (79%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/MockServiceClassComposerTest.java (81%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/MockServiceImplClassComposerTest.java (81%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/ServiceClientTestClassComposerTest.java (77%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/ServiceStubSettingsClassComposerTest.java (75%) create mode 100644 src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClientTest.golden rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/DeprecatedServiceStubSettings.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/EchoClientTest.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/EchoStubSettings.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcDeprecatedServiceCallableFactory.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcDeprecatedServiceStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcEchoCallableFactory.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcEchoStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcPublisherStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/GrpcTestingStub.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/LoggingClientTest.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/LoggingServiceV2StubSettings.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/MockDeprecatedService.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/MockDeprecatedServiceImpl.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/MockEcho.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/MockEchoImpl.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/PublisherStubSettings.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/SubscriberClientTest.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => grpc}/goldens/TestingClientTest.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => resourcename}/goldens/AgentName.golden (100%) create mode 100644 src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BUILD.bazel rename src/test/java/com/google/api/generator/gapic/composer/{ => resourcename}/goldens/BillingAccountLocationName.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => resourcename}/goldens/FoobarName.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => resourcename}/goldens/SessionName.golden (100%) rename src/test/java/com/google/api/generator/gapic/composer/{ => resourcename}/goldens/TestName.golden (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 33b7738029..ba9def0fea 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -46,7 +46,7 @@ jobs: echo "The old one will disappear after 7 days." - name: Unit Tests - run: bazel --batch test $(bazel query "//src/test/..." | grep "Test$") --noshow_progress + run: bazel --batch test $(bazel query "//src/test/..." | grep "Test$") --noshow_progress --test_output=errors - name: Integration Tests run: bazel --batch test //test/integration:asset //test/integration:credentials //test/integration:iam //test/integration:kms //test/integration:logging //test/integration:redis //test/integration:library --noshow_progress diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ca661a4d7..df4f90c1fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.0.6](https://www.github.com/googleapis/gapic-generator-java/compare/v1.0.5...v1.0.6) (2021-05-19) + + +### Bug Fixes + +* **mixins:** Gate mixin RPC on HTTP rules, add yaml doc/http overrides ([#727](https://www.github.com/googleapis/gapic-generator-java/issues/727)) ([229da5d](https://www.github.com/googleapis/gapic-generator-java/commit/229da5d94cf7db060abf3ea006a20d1ade804597)) + ### [1.0.5](https://www.github.com/googleapis/gapic-generator-java/compare/v1.0.4...v1.0.5) (2021-05-17) diff --git a/dependencies.properties b/dependencies.properties index 53a7e8ee12..841111924b 100644 --- a/dependencies.properties +++ b/dependencies.properties @@ -11,12 +11,11 @@ version.com_google_protobuf=3.13.0 # Version of google-java-format is downgraded from 1.8 to 1.7, because 1.8 supports java 11 minimum, while our JRE is java 8. version.google_java_format=1.7 version.com_google_api_common_java=1.9.3 -# TODO(miraleung): Update this. version.com_google_gax_java=1.62.0 version.io_grpc_java=1.30.2 # Common deps. -maven.com_google_guava_guava=com.google.guava:guava:26.0-jre +maven.com_google_guava_guava=com.google.guava:guava:30.1-android maven.com_google_code_findbugs_jsr305=com.google.code.findbugs:jsr305:3.0.0 maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.7.2 maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.7.2 diff --git a/src/main/java/com/google/api/generator/gapic/composer/ClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ClassComposer.java deleted file mode 100644 index 56900ba5ec..0000000000 --- a/src/main/java/com/google/api/generator/gapic/composer/ClassComposer.java +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.api.generator.gapic.composer; - -public interface ClassComposer - extends com.google.api.generator.gapic.composer.common.ClassComposer {} diff --git a/src/main/java/com/google/api/generator/gapic/composer/Composer.java b/src/main/java/com/google/api/generator/gapic/composer/Composer.java index 1d9c04b27d..8dd716eb2a 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/Composer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/Composer.java @@ -17,7 +17,15 @@ import com.google.api.generator.engine.ast.ClassDefinition; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.gapic.composer.comment.CommentComposer; +import com.google.api.generator.gapic.composer.common.ServiceClientClassComposer; +import com.google.api.generator.gapic.composer.common.ServiceStubClassComposer; +import com.google.api.generator.gapic.composer.grpc.GrpcServiceCallableFactoryClassComposer; +import com.google.api.generator.gapic.composer.grpc.GrpcServiceStubClassComposer; +import com.google.api.generator.gapic.composer.grpc.MockServiceClassComposer; +import com.google.api.generator.gapic.composer.grpc.MockServiceImplClassComposer; +import com.google.api.generator.gapic.composer.grpc.ServiceClientTestClassComposer; import com.google.api.generator.gapic.composer.grpc.ServiceSettingsClassComposer; +import com.google.api.generator.gapic.composer.grpc.ServiceStubSettingsClassComposer; import com.google.api.generator.gapic.composer.resourcename.ResourceNameHelperClassComposer; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; diff --git a/src/main/java/com/google/api/generator/gapic/composer/comment/StubCommentComposer.java b/src/main/java/com/google/api/generator/gapic/composer/comment/StubCommentComposer.java index 01ecd36e66..8ce682188f 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/comment/StubCommentComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/comment/StubCommentComposer.java @@ -31,21 +31,12 @@ public class StubCommentComposer { private static final String ADVANCED_USAGE_API_REFLECTION_DESCRIPTION = "This class is for advanced usage and reflects the underlying API directly."; - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - private static final StubCommentComposer GRPC_INSTANCE = new StubCommentComposer("gRPC"); - private final String transportPrefix; public StubCommentComposer(String transportPrefix) { this.transportPrefix = transportPrefix; } - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - public static List createGrpcServiceStubClassHeaderComments( - String serviceName, boolean isDeprecated) { - return GRPC_INSTANCE.createTransportServiceStubClassHeaderComments(serviceName, isDeprecated); - } - public List createTransportServiceStubClassHeaderComments( String serviceName, boolean isDeprecated) { JavaDocComment.Builder javaDocBuilder = JavaDocComment.builder(); @@ -63,13 +54,6 @@ public List createTransportServiceStubClassHeaderComments( .build())); } - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - public static List createGrpcServiceCallableFactoryClassHeaderComments( - String serviceName, boolean isDeprecated) { - return GRPC_INSTANCE.createTransportServiceCallableFactoryClassHeaderComments( - serviceName, isDeprecated); - } - public List createTransportServiceCallableFactoryClassHeaderComments( String serviceName, boolean isDeprecated) { JavaDocComment.Builder javaDocBuilder = JavaDocComment.builder(); diff --git a/src/main/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java similarity index 57% rename from src/main/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java index c770d7cd76..280c9712b2 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceCallableFactoryClassComposer.java @@ -12,12 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.core.BetaApi; -import com.google.api.gax.grpc.GrpcCallSettings; -import com.google.api.gax.grpc.GrpcCallableFactory; -import com.google.api.gax.grpc.GrpcStubCallableFactory; import com.google.api.gax.rpc.BatchingCallSettings; import com.google.api.gax.rpc.BidiStreamingCallable; import com.google.api.gax.rpc.ClientContext; @@ -40,43 +37,43 @@ import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.comment.StubCommentComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.composer.utils.PackageChecker; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; -import com.google.common.base.Preconditions; -import com.google.longrunning.Operation; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import javax.annotation.Generated; -public class GrpcServiceCallableFactoryClassComposer implements ClassComposer { - private static final GrpcServiceCallableFactoryClassComposer INSTANCE = - new GrpcServiceCallableFactoryClassComposer(); - private static final String DOT = "."; +public abstract class AbstractServiceCallableFactoryClassComposer implements ClassComposer { + private final TransportContext transportContext; - private GrpcServiceCallableFactoryClassComposer() {} + protected AbstractServiceCallableFactoryClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } - public static GrpcServiceCallableFactoryClassComposer instance() { - return INSTANCE; + protected TransportContext getTransportContext() { + return transportContext; } @Override - public GapicClass generate(GapicContext ignored, Service service) { - TypeStore typeStore = createTypes(service); - String className = ClassNames.getGrpcServiceCallableFactoryClassName(service); + public GapicClass generate(GapicContext context, Service service) { + TypeStore typeStore = createTypes(); + String className = + getTransportContext().classNames().getTransportServiceCallableFactoryClassName(service); GapicClass.Kind kind = Kind.STUB; String pakkage = String.format("%s.stub", service.pakkage()); + StubCommentComposer commentComposer = + new StubCommentComposer(getTransportContext().transportName()); ClassDefinition classDef = ClassDefinition.builder() .setPackageString(pakkage) .setHeaderCommentStatements( - StubCommentComposer.createGrpcServiceCallableFactoryClassHeaderComments( + commentComposer.createTransportServiceCallableFactoryClassHeaderComments( service.name(), service.isDeprecated())) .setAnnotations(createClassAnnotations(service, typeStore)) .setImplementsTypes(createClassImplements(typeStore)) @@ -87,7 +84,7 @@ public GapicClass generate(GapicContext ignored, Service service) { return GapicClass.create(kind, classDef); } - private static List createClassAnnotations(Service service, TypeStore typeStore) { + protected List createClassAnnotations(Service service, TypeStore typeStore) { List annotations = new ArrayList<>(); if (!PackageChecker.isGaApi(service.pakkage())) { annotations.add(AnnotationNode.withType(typeStore.get("BetaApi"))); @@ -105,22 +102,17 @@ private static List createClassAnnotations(Service service, Type return annotations; } - private static List createClassImplements(TypeStore typeStore) { - return Arrays.asList(typeStore.get("GrpcStubCallableFactory")); - } + protected abstract List createClassImplements(TypeStore typeStore); - private static List createClassMethods(TypeStore typeStore) { + protected List createClassMethods(TypeStore typeStore) { return Arrays.asList( createUnaryCallableMethod(typeStore), createPagedCallableMethod(typeStore), createBatchingCallableMethod(typeStore), - createOperationCallableMethod(typeStore), - createBidiStreamingCallableMethod(typeStore), - createServerStreamingCallableMethod(typeStore), - createClientStreamingCallableMethod(typeStore)); + createOperationCallableMethod(typeStore)); } - private static MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { + protected MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { String methodVariantName = "Unary"; String requestTemplateName = "RequestT"; String responseTemplateName = "ResponseT"; @@ -131,7 +123,7 @@ private static MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { /*returnCallableKindName=*/ methodVariantName, /*returnCallableTemplateNames=*/ methodTemplateNames, /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + /*transportCallSettingsTemplateObjects=*/ methodTemplateNames.stream() .map(n -> (Object) n) .collect(Collectors.toList()), /*callSettingsVariantName=*/ methodVariantName, @@ -140,7 +132,7 @@ private static MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { .collect(Collectors.toList())); } - private static MethodDefinition createPagedCallableMethod(TypeStore typeStore) { + protected MethodDefinition createPagedCallableMethod(TypeStore typeStore) { String methodVariantName = "Paged"; String requestTemplateName = "RequestT"; String pagedResponseTemplateName = "PagedListResponseT"; @@ -154,7 +146,7 @@ private static MethodDefinition createPagedCallableMethod(TypeStore typeStore) { /*returnCallableTemplateNames=*/ Arrays.asList( requestTemplateName, pagedResponseTemplateName), /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ Arrays.asList( + /*transportCallSettingsTemplateObjects=*/ Arrays.asList( requestTemplateName, responseTemplateName), /*callSettingsVariantName=*/ methodVariantName, /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() @@ -162,7 +154,7 @@ private static MethodDefinition createPagedCallableMethod(TypeStore typeStore) { .collect(Collectors.toList())); } - private static MethodDefinition createBatchingCallableMethod(TypeStore typeStore) { + protected MethodDefinition createBatchingCallableMethod(TypeStore typeStore) { String methodVariantName = "Batching"; String requestTemplateName = "RequestT"; String responseTemplateName = "ResponseT"; @@ -173,67 +165,7 @@ private static MethodDefinition createBatchingCallableMethod(TypeStore typeStore /*returnCallableKindName=*/ "Unary", /*returnCallableTemplateNames=*/ methodTemplateNames, /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList()), - /*callSettingsVariantName=*/ methodVariantName, - /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList())); - } - - private static MethodDefinition createOperationCallableMethod(TypeStore typeStore) { - String methodVariantName = "Operation"; - String requestTemplateName = "RequestT"; - String responseTemplateName = "ResponseT"; - List methodTemplateNames = - Arrays.asList(requestTemplateName, responseTemplateName, "MetadataT"); - return createGenericCallableMethod( - typeStore, - /*methodTemplateNames=*/ methodTemplateNames, - /*returnCallableKindName=*/ methodVariantName, - /*returnCallableTemplateNames=*/ methodTemplateNames, - /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ Arrays.asList( - requestTemplateName, typeStore.get("Operation")), - /*callSettingsVariantName=*/ methodVariantName, - /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList())); - } - - private static MethodDefinition createBidiStreamingCallableMethod(TypeStore typeStore) { - String methodVariantName = "BidiStreaming"; - String requestTemplateName = "RequestT"; - String responseTemplateName = "ResponseT"; - List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); - return createGenericCallableMethod( - typeStore, - /*methodTemplateNames=*/ methodTemplateNames, - /*returnCallableKindName=*/ methodVariantName, - /*returnCallableTemplateNames=*/ methodTemplateNames, - /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList()), - /*callSettingsVariantName=*/ "Streaming", - /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList())); - } - - private static MethodDefinition createServerStreamingCallableMethod(TypeStore typeStore) { - String methodVariantName = "ServerStreaming"; - String requestTemplateName = "RequestT"; - String responseTemplateName = "ResponseT"; - List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); - return createGenericCallableMethod( - typeStore, - /*methodTemplateNames=*/ methodTemplateNames, - /*returnCallableKindName=*/ methodVariantName, - /*returnCallableTemplateNames=*/ methodTemplateNames, - /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + /*transportCallSettingsTemplateObjects=*/ methodTemplateNames.stream() .map(n -> (Object) n) .collect(Collectors.toList()), /*callSettingsVariantName=*/ methodVariantName, @@ -242,40 +174,21 @@ private static MethodDefinition createServerStreamingCallableMethod(TypeStore ty .collect(Collectors.toList())); } - private static MethodDefinition createClientStreamingCallableMethod(TypeStore typeStore) { - String methodVariantName = "ClientStreaming"; - String requestTemplateName = "RequestT"; - String responseTemplateName = "ResponseT"; - List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); - return createGenericCallableMethod( - typeStore, - /*methodTemplateNames=*/ methodTemplateNames, - /*returnCallableKindName=*/ methodVariantName, - /*returnCallableTemplateNames=*/ methodTemplateNames, - /*methodVariantName=*/ methodVariantName, - /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList()), - /*callSettingsVariantName=*/ "Streaming", - /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() - .map(n -> (Object) n) - .collect(Collectors.toList())); - } + protected abstract MethodDefinition createOperationCallableMethod(TypeStore typeStore); - private static MethodDefinition createGenericCallableMethod( + protected MethodDefinition createGenericCallableMethod( TypeStore typeStore, List methodTemplateNames, String returnCallableKindName, List returnCallableTemplateNames, String methodVariantName, - List grpcCallSettingsTemplateObjects, + List transportCallSettingsTemplateObjects, String callSettingsVariantName, List callSettingsTemplateObjects) { String methodName = String.format("create%sCallable", methodVariantName); String callSettingsTypeName = String.format("%sCallSettings", callSettingsVariantName); String returnTypeName = String.format("%sCallable", returnCallableKindName); - String grpcCallSettingsTypeName = "GrpcCallSettings"; boolean isOperationCallable = methodVariantName.equals("Operation"); List arguments = new ArrayList<>(); @@ -283,11 +196,11 @@ private static MethodDefinition createGenericCallableMethod( VariableExpr.builder() .setVariable( Variable.builder() - .setName("grpcCallSettings") - .setType(typeStore.get(grpcCallSettingsTypeName)) + .setName(getTransportContext().transportCallSettingsName()) + .setType(getTransportContext().transportCallSettingsType()) .build()) .setIsDecl(true) - .setTemplateObjects(grpcCallSettingsTemplateObjects) + .setTemplateObjects(transportCallSettingsTemplateObjects) .build()); arguments.add( VariableExpr.builder() @@ -314,22 +227,17 @@ private static MethodDefinition createGenericCallableMethod( .setVariable( Variable.builder() .setName("operationsStub") - .setType(typeStore.get("OperationsStub")) + .setType(getTransportContext().operationsStubType()) .build()) .setIsDecl(true) .build()); } - String grpcCallableFactoryTypeName = "GrpcCallableFactory"; - TypeNode grpcCallableFactoryType = typeStore.get(grpcCallableFactoryTypeName); - Preconditions.checkNotNull( - grpcCallableFactoryType, String.format("Type %s not found", grpcCallableFactoryTypeName)); - TypeNode returnType = typeStore.get(returnTypeName); MethodInvocationExpr returnExpr = MethodInvocationExpr.builder() .setMethodName(methodName) - .setStaticReferenceType(grpcCallableFactoryType) + .setStaticReferenceType(getTransportContext().transportCallableFactoryType()) .setArguments( arguments.stream() .map(v -> v.toBuilder().setIsDecl(false).build()) @@ -349,7 +257,7 @@ private static MethodDefinition createGenericCallableMethod( .build(); } - private static TypeStore createTypes(Service service) { + private static TypeStore createTypes() { List concreteClazzes = Arrays.asList( // Gax-java classes. @@ -366,15 +274,8 @@ private static TypeStore createTypes(Service service) { StreamingCallSettings.class, UnaryCallSettings.class, UnaryCallable.class, - // gax-java gRPC classes. - GrpcCallSettings.class, - GrpcCallableFactory.class, - GrpcStubCallableFactory.class, Generated.class, - Operation.class, UnsupportedOperationException.class); - TypeStore typeStore = new TypeStore(concreteClazzes); - typeStore.put("com.google.longrunning.stub", "OperationsStub"); - return typeStore; + return new TypeStore(concreteClazzes); } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java new file mode 100644 index 0000000000..7f45e974b3 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientTestClassComposer.java @@ -0,0 +1,969 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.common; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.ApiStreamObserver; +import com.google.api.gax.rpc.BidiStreamingCallable; +import com.google.api.gax.rpc.ClientStreamingCallable; +import com.google.api.gax.rpc.InvalidArgumentException; +import com.google.api.gax.rpc.OperationCallSettings; +import com.google.api.gax.rpc.PagedCallSettings; +import com.google.api.gax.rpc.ServerStreamingCallSettings; +import com.google.api.gax.rpc.ServerStreamingCallable; +import com.google.api.gax.rpc.StatusCode; +import com.google.api.gax.rpc.StreamingCallSettings; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.CastExpr; +import com.google.api.generator.engine.ast.ClassDefinition; +import com.google.api.generator.engine.ast.CommentStatement; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EmptyLineStatement; +import com.google.api.generator.engine.ast.EnumRefExpr; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.InstanceofExpr; +import com.google.api.generator.engine.ast.LineComment; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.NewObjectExpr; +import com.google.api.generator.engine.ast.PrimitiveValue; +import com.google.api.generator.engine.ast.Reference; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.Statement; +import com.google.api.generator.engine.ast.StringObjectValue; +import com.google.api.generator.engine.ast.TryCatchStatement; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.VaporReference; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.defaultvalue.DefaultValueComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Field; +import com.google.api.generator.gapic.model.GapicClass; +import com.google.api.generator.gapic.model.GapicClass.Kind; +import com.google.api.generator.gapic.model.GapicContext; +import com.google.api.generator.gapic.model.Message; +import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.MethodArgument; +import com.google.api.generator.gapic.model.ResourceName; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.longrunning.Operation; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.Any; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import javax.annotation.Generated; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public abstract class AbstractServiceClientTestClassComposer implements ClassComposer { + protected static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); + + protected static final String CLIENT_VAR_NAME = "client"; + private static final String MOCK_SERVICE_VAR_NAME_PATTERN = "mock%s"; + private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; + + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + protected static final AnnotationNode TEST_ANNOTATION = + AnnotationNode.withType(FIXED_TYPESTORE.get("Test")); + + private final TransportContext transportContext; + + protected AbstractServiceClientTestClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + public TransportContext getTransportContext() { + return transportContext; + } + + @Override + public GapicClass generate(GapicContext context, Service service) { + Map resourceNames = context.helperResourceNames(); + Map messageTypes = context.messages(); + String pakkage = service.pakkage(); + TypeStore typeStore = new TypeStore(); + addDynamicTypes(context, service, typeStore); + String className = ClassNames.getServiceClientTestClassName(service); + GapicClass.Kind kind = Kind.MAIN; + + Map classMemberVarExprs = + createClassMemberVarExprs(service, context, typeStore); + + ClassDefinition classDef = + ClassDefinition.builder() + .setPackageString(pakkage) + .setAnnotations(createClassAnnotations()) + .setScope(ScopeNode.PUBLIC) + .setName(className) + .setStatements(createClassMemberFieldDecls(classMemberVarExprs)) + .setMethods( + createClassMethods(service, context, classMemberVarExprs, typeStore, resourceNames)) + .build(); + return GapicClass.create(kind, classDef); + } + + private List createClassAnnotations() { + return Arrays.asList( + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("Generated")) + .setDescription("by gapic-generator-java") + .build()); + } + + protected abstract Map createClassMemberVarExprs( + Service service, GapicContext context, TypeStore typeStore); + + protected List createClassMemberFieldDecls( + Map classMemberVarExprs) { + return classMemberVarExprs.values().stream() + .map( + v -> + ExprStatement.withExpr( + v.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsStatic(v.type().reference().name().startsWith("Mock")) + .build())) + .collect(Collectors.toList()); + } + + private List createClassMethods( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore, + Map resourceNames) { + List javaMethods = new ArrayList<>(); + javaMethods.addAll(createTestAdminMethods(service, context, classMemberVarExprs, typeStore)); + javaMethods.addAll(createTestMethods(service, context, classMemberVarExprs, resourceNames)); + return javaMethods; + } + + private List createTestAdminMethods( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore) { + List javaMethods = new ArrayList<>(); + javaMethods.add( + createStartStaticServerMethod(service, context, classMemberVarExprs, typeStore)); + javaMethods.add(createStopServerMethod(service, classMemberVarExprs)); + javaMethods.add(createSetUpMethod(service, classMemberVarExprs, typeStore)); + javaMethods.add(createTearDownMethod(service, classMemberVarExprs)); + return javaMethods; + } + + protected abstract MethodDefinition createStartStaticServerMethod( + Service service, + GapicContext context, + Map classMemberVarExprs, + TypeStore typeStore); + + protected abstract MethodDefinition createStopServerMethod( + Service service, Map classMemberVarExprs); + + protected abstract MethodDefinition createSetUpMethod( + Service service, Map classMemberVarExprs, TypeStore typeStore); + + protected abstract MethodDefinition createTearDownMethod( + Service service, Map classMemberVarExprs); + + private List createTestMethods( + Service service, + GapicContext context, + Map classMemberVarExprs, + Map resourceNames) { + Map messageTypes = context.messages(); + List javaMethods = new ArrayList<>(); + for (Method method : service.methods()) { + Service matchingService = service; + if (method.isMixin()) { + int dotIndex = method.mixedInApiName().lastIndexOf("."); + String mixinServiceName = method.mixedInApiName().substring(dotIndex + 1); + String mixinServiceProtoPackage = method.mixedInApiName().substring(0, dotIndex); + Optional mixinServiceOpt = + context.mixinServices().stream() + .filter( + s -> + s.name().equals(mixinServiceName) + && s.protoPakkage().equals(mixinServiceProtoPackage)) + .findFirst(); + if (mixinServiceOpt.isPresent()) { + matchingService = mixinServiceOpt.get(); + } + } + + // Ignore variants for streaming methods as well. + if (method.methodSignatures().isEmpty() || !method.stream().equals(Method.Stream.NONE)) { + javaMethods.add( + createRpcTestMethod( + method, + service, + matchingService, + Collections.emptyList(), + 0, + true, + classMemberVarExprs, + resourceNames, + messageTypes)); + javaMethods.add( + createRpcExceptionTestMethod( + method, + matchingService, + Collections.emptyList(), + 0, + classMemberVarExprs, + resourceNames, + messageTypes)); + } else { + for (int i = 0; i < method.methodSignatures().size(); i++) { + javaMethods.add( + createRpcTestMethod( + method, + service, + matchingService, + method.methodSignatures().get(i), + i, + false, + classMemberVarExprs, + resourceNames, + messageTypes)); + javaMethods.add( + createRpcExceptionTestMethod( + method, + matchingService, + method.methodSignatures().get(i), + i, + classMemberVarExprs, + resourceNames, + messageTypes)); + } + } + } + return javaMethods; + } + + /** + * Creates a test method for a given RPC, e.g. createAssetTest. + * + * @param method the RPC for which this test method is created. + * @param apiService the host service under test. + * @param rpcService the service that {@code method} belongs to. This is not equal to {@code + * apiService} only when {@code method} is a mixin, in which case {@code rpcService} is the + * mixed-in service. If {@code apiService} and {@code rpcService} are different, they will be + * used only for pagination. Otherwise, {@code rpcService} subsumes {@code apiService}. + * @param methodSignature the method signature of the RPC under test. + * @param variantIndex the nth variant of the RPC under test. This applies when we have + * polymorphism due to the presence of several method signature annotations in the proto. + * @param isRequestArg whether the RPC variant under test take only the request proto message. + * @param classMemberVarExprs the class members in the generated test class. + * @param resourceNames the resource names available for use. + * @param messageTypes the proto message types available for use. + */ + private MethodDefinition createRpcTestMethod( + Method method, + Service apiService, + Service rpcService, + List methodSignature, + int variantIndex, + boolean isRequestArg, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + if (!method.stream().equals(Method.Stream.NONE)) { + return createStreamingRpcTestMethod( + rpcService, method, classMemberVarExprs, resourceNames, messageTypes); + } + // Construct the expected response. + TypeNode methodOutputType = method.hasLro() ? method.lro().responseType() : method.outputType(); + List methodExprs = new ArrayList<>(); + + TypeNode repeatedResponseType = null; + VariableExpr responsesElementVarExpr = null; + String mockServiceVarName = getMockServiceVarName(rpcService); + if (method.isPaged()) { + Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); + Field repeatedPagedResultsField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); + Preconditions.checkNotNull( + repeatedPagedResultsField, + String.format( + "No repeated field found for paged method %s with output message type %s", + method.name(), methodOutputMessage.name())); + + // Must be a non-repeated type. + repeatedResponseType = repeatedPagedResultsField.type(); + responsesElementVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(repeatedResponseType).setName("responsesElement").build()); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(responsesElementVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + DefaultValueComposer.createDefaultValue( + Field.builder() + .setType(repeatedResponseType) + .setName("responsesElement") + .setIsMessage(!repeatedResponseType.isProtoPrimitiveType()) + .build())) + .build()); + } + + VariableExpr expectedResponseVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(methodOutputType).setName("expectedResponse").build()); + Expr expectedResponseValExpr = null; + if (method.isPaged()) { + Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); + Field firstRepeatedField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); + Preconditions.checkNotNull( + firstRepeatedField, + String.format( + "Expected paged RPC %s to have a repeated field in the response %s but found none", + method.name(), methodOutputMessage.name())); + + expectedResponseValExpr = + DefaultValueComposer.createSimplePagedResponse( + method.outputType(), firstRepeatedField.name(), responsesElementVarExpr); + } else { + if (messageTypes.containsKey(methodOutputType.reference().fullName())) { + expectedResponseValExpr = + DefaultValueComposer.createSimpleMessageBuilderExpr( + messageTypes.get(methodOutputType.reference().fullName()), + resourceNames, + messageTypes); + } else { + // Wrap this in a field so we don't have to split the helper into lots of different methods, + // or duplicate it for VariableExpr. + expectedResponseValExpr = + DefaultValueComposer.createDefaultValue( + Field.builder() + .setType(methodOutputType) + .setIsMessage(true) + .setName("expectedResponse") + .build()); + } + } + + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(expectedResponseVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(expectedResponseValExpr) + .build()); + + if (method.hasLro()) { + VariableExpr resultOperationVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType(FIXED_TYPESTORE.get("Operation")) + .setName("resultOperation") + .build()); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(resultOperationVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + DefaultValueComposer.createSimpleOperationBuilderExpr( + String.format("%sTest", JavaStyle.toLowerCamelCase(method.name())), + expectedResponseVarExpr)) + .build()); + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(mockServiceVarName)) + .setMethodName("addResponse") + .setArguments(resultOperationVarExpr) + .build()); + } else { + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(mockServiceVarName)) + .setMethodName("addResponse") + .setArguments(expectedResponseVarExpr) + .build()); + } + List methodStatements = new ArrayList<>(); + methodStatements.addAll( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + methodExprs.clear(); + methodStatements.add(EMPTY_LINE_STATEMENT); + + // Construct the request or method arguments. + VariableExpr requestVarExpr = null; + Message requestMessage = null; + List argExprs = new ArrayList<>(); + if (isRequestArg) { + requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + argExprs.add(requestVarExpr); + requestMessage = messageTypes.get(method.inputType().reference().fullName()); + Preconditions.checkNotNull(requestMessage); + Expr valExpr = + DefaultValueComposer.createSimpleMessageBuilderExpr( + requestMessage, resourceNames, messageTypes); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(valExpr) + .build()); + } else { + for (MethodArgument methodArg : methodSignature) { + String methodArgName = JavaStyle.toLowerCamelCase(methodArg.name()); + VariableExpr varExpr = + VariableExpr.withVariable( + Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); + argExprs.add(varExpr); + Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(valExpr) + .build()); + } + } + methodStatements.addAll( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + methodExprs.clear(); + methodStatements.add(EMPTY_LINE_STATEMENT); + + // Call the RPC Java method. + VariableExpr actualResponseVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + !method.isPaged() + ? methodOutputType + // If this method is a paginated mixin, use the host service, since + // ServiceClient defines the paged response class and the mixed-in service + // does not have a client. + : getPagedResponseType(method, method.isMixin() ? apiService : rpcService)) + .setName(method.isPaged() ? "pagedListResponse" : "actualResponse") + .build()); + Expr rpcJavaMethodInvocationExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get("client")) + .setMethodName( + JavaStyle.toLowerCamelCase(method.name()) + (method.hasLro() ? "Async" : "")) + .setArguments(argExprs.stream().map(e -> (Expr) e).collect(Collectors.toList())) + .setReturnType(actualResponseVarExpr.type()) + .build(); + if (method.hasLro()) { + rpcJavaMethodInvocationExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(rpcJavaMethodInvocationExpr) + .setMethodName("get") + .setReturnType(rpcJavaMethodInvocationExpr.type()) + .build(); + } + + boolean returnsVoid = isProtoEmptyType(methodOutputType); + if (returnsVoid) { + methodExprs.add(rpcJavaMethodInvocationExpr); + } else { + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(actualResponseVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(rpcJavaMethodInvocationExpr) + .build()); + } + + if (method.isPaged()) { + // Assign the resources variable. + VariableExpr resourcesVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(List.class) + .setGenerics(Arrays.asList(repeatedResponseType.reference())) + .build())) + .setName("resources") + .build()); + Expr iterateAllExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(actualResponseVarExpr) + .setMethodName("iterateAll") + .build(); + Expr resourcesValExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Lists")) + .setMethodName("newArrayList") + .setArguments(iterateAllExpr) + .setReturnType(resourcesVarExpr.type()) + .build(); + + methodStatements.addAll( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + methodExprs.clear(); + methodStatements.add(EMPTY_LINE_STATEMENT); + + methodStatements.add( + ExprStatement.withExpr( + AssignmentExpr.builder() + .setVariableExpr(resourcesVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(resourcesValExpr) + .build())); + methodStatements.add(EMPTY_LINE_STATEMENT); + + // Assert the size is equivalent. + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setMethodName("assertEquals") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), + MethodInvocationExpr.builder() + .setExprReferenceExpr(resourcesVarExpr) + .setMethodName("size") + .setReturnType(TypeNode.INT) + .build()) + .build()); + + // Assert the responses are equivalent. + Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); + Field repeatedPagedResultsField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); + Preconditions.checkNotNull( + repeatedPagedResultsField, + String.format( + "No repeated field found for paged method %s with output message type %s", + method.name(), methodOutputMessage.name())); + + Expr zeroExpr = + ValueExpr.withValue(PrimitiveValue.builder().setType(TypeNode.INT).setValue("0").build()); + Expr expectedPagedResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(expectedResponseVarExpr) + .setMethodName( + String.format( + "get%sList", JavaStyle.toUpperCamelCase(repeatedPagedResultsField.name()))) + .build(); + expectedPagedResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(expectedPagedResponseExpr) + .setMethodName("get") + .setArguments(zeroExpr) + .build(); + Expr actualPagedResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(resourcesVarExpr) + .setMethodName("get") + .setArguments(zeroExpr) + .build(); + + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setMethodName("assertEquals") + .setArguments(expectedPagedResponseExpr, actualPagedResponseExpr) + .build()); + } else if (!returnsVoid) { + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setMethodName("assertEquals") + .setArguments(expectedResponseVarExpr, actualResponseVarExpr) + .build()); + } + methodStatements.addAll( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + methodExprs.clear(); + methodStatements.add(EMPTY_LINE_STATEMENT); + + methodStatements.addAll( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); + methodExprs.clear(); + + methodStatements.addAll( + constructRpcTestCheckerLogic( + method, + rpcService, + isRequestArg, + classMemberVarExprs, + requestVarExpr, + requestMessage, + argExprs)); + + String testMethodName = + String.format( + "%sTest%s", + JavaStyle.toLowerCamelCase(method.name()), variantIndex > 0 ? variantIndex + 1 : ""); + + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(TEST_ANNOTATION)) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName(testMethodName) + .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class))) + .setBody(methodStatements) + .build(); + } + + protected abstract List constructRpcTestCheckerLogic( + Method method, + Service service, + boolean isRequestArg, + Map classMemberVarExprs, + VariableExpr requestVarExpr, + Message requestMessage, + List argExprs); + + protected abstract MethodDefinition createStreamingRpcTestMethod( + Service service, + Method method, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes); + + /** + * Creates a test method to exercise exceptions for a given RPC, e.g. createAssetTest. + * + * @param method the RPC for which this test method is created. + * @param service the service that {@code method} belongs to. + * @param methodSignature the method signature of the RPC under test. + * @param variantIndex the nth variant of the RPC under test. This applies when we have + * polymorphism due to the presence of several method signature annotations in the proto. + * @param classMemberVarExprs the class members in the generated test class. + * @param resourceNames the resource names available for use. + * @param messageTypes the proto message types available for use. + */ + protected abstract MethodDefinition createRpcExceptionTestMethod( + Method method, + Service service, + List methodSignature, + int variantIndex, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes); + + protected abstract List createStreamingRpcExceptionTestStatements( + Method method, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes); + + protected List createRpcExceptionTestStatements( + Method method, + List methodSignature, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + List argVarExprs = new ArrayList<>(); + List tryBodyExprs = new ArrayList<>(); + if (methodSignature.isEmpty()) { + // Construct the actual request. + VariableExpr varExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + argVarExprs.add(varExpr); + Message requestMessage = messageTypes.get(method.inputType().reference().fullName()); + Preconditions.checkNotNull(requestMessage); + Expr valExpr = + DefaultValueComposer.createSimpleMessageBuilderExpr( + requestMessage, resourceNames, messageTypes); + tryBodyExprs.add( + AssignmentExpr.builder() + .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(valExpr) + .build()); + } else { + for (MethodArgument methodArg : methodSignature) { + String methodArgName = JavaStyle.toLowerCamelCase(methodArg.name()); + VariableExpr varExpr = + VariableExpr.withVariable( + Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); + argVarExprs.add(varExpr); + Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); + tryBodyExprs.add( + AssignmentExpr.builder() + .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(valExpr) + .build()); + } + } + String rpcJavaName = JavaStyle.toLowerCamelCase(method.name()); + if (method.hasLro()) { + rpcJavaName += "Async"; + } + MethodInvocationExpr rpcJavaMethodInvocationExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get("client")) + .setMethodName(rpcJavaName) + .setArguments(argVarExprs.stream().map(e -> (Expr) e).collect(Collectors.toList())) + .build(); + if (method.hasLro()) { + rpcJavaMethodInvocationExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(rpcJavaMethodInvocationExpr) + .setMethodName("get") + .build(); + } + tryBodyExprs.add(rpcJavaMethodInvocationExpr); + + VariableExpr catchExceptionVarExpr = + VariableExpr.builder() + .setVariable( + Variable.builder() + .setType( + TypeNode.withExceptionClazz( + method.hasLro() + ? ExecutionException.class + : InvalidArgumentException.class)) + .setName("e") + .build()) + .build(); + + List catchBody = + method.hasLro() + ? createRpcLroExceptionTestCatchBody(catchExceptionVarExpr, false) + : Arrays.asList( + CommentStatement.withComment(LineComment.withComment("Expected exception."))); + // Assert a failure if no exception was raised. + tryBodyExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) + .setMethodName("fail") + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("No exception raised"))) + .build()); + + TryCatchStatement tryCatchBlock = + TryCatchStatement.builder() + .setTryBody( + tryBodyExprs.stream() + .map(e -> ExprStatement.withExpr(e)) + .collect(Collectors.toList())) + .setCatchVariableExpr(catchExceptionVarExpr.toBuilder().setIsDecl(true).build()) + .setCatchBody(catchBody) + .build(); + + return Arrays.asList(EMPTY_LINE_STATEMENT, tryCatchBlock); + } + + protected abstract List createRpcLroExceptionTestCatchBody( + VariableExpr exceptionExpr, boolean isStreaming); + + /* ========================================= + * Type creator methods. + * ========================================= + */ + + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + AbstractMessage.class, + After.class, + AfterClass.class, + Any.class, + ApiClientHeaderProvider.class, + ApiStreamObserver.class, + Arrays.class, + Assert.class, + Before.class, + BeforeClass.class, + BidiStreamingCallable.class, + ClientStreamingCallable.class, + ExecutionException.class, + Generated.class, + IOException.class, + InvalidArgumentException.class, + List.class, + Lists.class, + NoCredentialsProvider.class, + Operation.class, + ServerStreamingCallable.class, + StatusCode.class, + Test.class, + UUID.class); + return new TypeStore(concreteClazzes); + } + + private void addDynamicTypes(GapicContext context, Service service, TypeStore typeStore) { + typeStore.putAll( + service.pakkage(), + Arrays.asList( + ClassNames.getMockServiceClassName(service), + ClassNames.getServiceClientClassName(service), + ClassNames.getServiceSettingsClassName(service), + getTransportContext().classNames().getTransportServiceStubClassName(service))); + // Pagination types. + typeStore.putAll( + service.pakkage(), + service.methods().stream() + .filter(m -> m.isPaged()) + .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) + .collect(Collectors.toList()), + true, + ClassNames.getServiceClientClassName(service)); + for (Service mixinService : context.mixinServices()) { + typeStore.put(mixinService.pakkage(), ClassNames.getMockServiceClassName(mixinService)); + for (Method mixinMethod : mixinService.methods()) { + if (!mixinMethod.isPaged()) { + continue; + } + typeStore.put( + service.pakkage(), + String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, mixinMethod.name()), + true, + ClassNames.getServiceClientClassName(service)); + } + } + } + + private static TypeNode getOperationCallSettingsTypeHelper( + Method protoMethod, boolean isBuilder) { + Preconditions.checkState( + protoMethod.hasLro(), + String.format("Cannot get OperationCallSettings on non-LRO method %s", protoMethod.name())); + Class callSettingsClazz = + isBuilder ? OperationCallSettings.Builder.class : OperationCallSettings.class; + return TypeNode.withReference( + ConcreteReference.builder() + .setClazz(callSettingsClazz) + .setGenerics( + Arrays.asList( + protoMethod.inputType().reference(), + protoMethod.lro().responseType().reference(), + protoMethod.lro().metadataType().reference())) + .build()); + } + + private static TypeNode getCallSettingsTypeHelper( + Method protoMethod, TypeStore typeStore, boolean isBuilder) { + Class callSettingsClazz = isBuilder ? UnaryCallSettings.Builder.class : UnaryCallSettings.class; + if (protoMethod.isPaged()) { + callSettingsClazz = isBuilder ? PagedCallSettings.Builder.class : PagedCallSettings.class; + } else { + switch (protoMethod.stream()) { + case CLIENT: + // Fall through. + case BIDI: + callSettingsClazz = + isBuilder ? StreamingCallSettings.Builder.class : StreamingCallSettings.class; + break; + case SERVER: + callSettingsClazz = + isBuilder + ? ServerStreamingCallSettings.Builder.class + : ServerStreamingCallSettings.class; + break; + case NONE: + // Fall through + default: + // Fall through + } + } + + List generics = new ArrayList<>(); + generics.add(protoMethod.inputType().reference()); + generics.add(protoMethod.outputType().reference()); + if (protoMethod.isPaged()) { + generics.add( + typeStore + .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, protoMethod.name())) + .reference()); + } + + return TypeNode.withReference( + ConcreteReference.builder().setClazz(callSettingsClazz).setGenerics(generics).build()); + } + + protected static TypeNode getCallableType(Method protoMethod) { + Preconditions.checkState( + !protoMethod.stream().equals(Method.Stream.NONE), + "No callable type exists for non-streaming methods."); + + Class callableClazz = ClientStreamingCallable.class; + switch (protoMethod.stream()) { + case BIDI: + callableClazz = BidiStreamingCallable.class; + break; + case SERVER: + callableClazz = ServerStreamingCallable.class; + break; + case CLIENT: + // Fall through. + case NONE: + // Fall through + default: + // Fall through + } + + List generics = new ArrayList<>(); + generics.add(protoMethod.inputType().reference()); + generics.add(protoMethod.outputType().reference()); + + return TypeNode.withReference( + ConcreteReference.builder().setClazz(callableClazz).setGenerics(generics).build()); + } + + private static TypeNode getPagedResponseType(Method method, Service service) { + return TypeNode.withReference( + VaporReference.builder() + .setName(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) + .setPakkage(service.pakkage()) + .setEnclosingClassNames(ClassNames.getServiceClientClassName(service)) + .setIsStaticImport(true) + .build()); + } + + protected static String getCallableMethodName(Method protoMethod) { + Preconditions.checkState( + !protoMethod.stream().equals(Method.Stream.NONE), + "No callable type exists for non-streaming methods."); + + switch (protoMethod.stream()) { + case BIDI: + return "bidiStreamingCall"; + case SERVER: + return "serverStreamingCall"; + case CLIENT: + // Fall through. + case NONE: + // Fall through + default: + return "clientStreamingCall"; + } + } + + protected String getMockServiceVarName(Service service) { + return String.format(MOCK_SERVICE_VAR_NAME_PATTERN, service.name()); + } + + private static boolean isProtoEmptyType(TypeNode type) { + return type.reference().pakkage().equals("com.google.protobuf") + && type.reference().name().equals("Empty"); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java index fdfa9c7177..14e79caab9 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java @@ -60,7 +60,6 @@ import com.google.api.generator.gapic.model.Method; import com.google.api.generator.gapic.model.Method.Stream; import com.google.api.generator.gapic.model.Service; -import com.google.api.generator.gapic.model.TransportContext; import com.google.api.generator.gapic.utils.JavaStyle; import com.google.common.base.Preconditions; import com.google.longrunning.Operation; @@ -83,6 +82,16 @@ public abstract class AbstractServiceSettingsClassComposer implements ClassCompo private static final String SETTINGS_LITERAL = "Settings"; private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + private final TransportContext transportContext; + + protected AbstractServiceSettingsClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + protected TransportContext getTransportContext() { + return transportContext; + } + @Override public GapicClass generate(GapicContext context, Service service) { String pakkage = service.pakkage(); @@ -108,7 +117,7 @@ public GapicClass generate(GapicContext context, Service service) { typeStore .get(ClassNames.getServiceSettingsClassName(service)) .reference())))) - .setMethods(createClassMethods(context.transportContext(), service, typeStore)) + .setMethods(createClassMethods(service, typeStore)) .setNestedClasses(Arrays.asList(createNestedBuilderClass(service, typeStore))) .build(); return GapicClass.create(kind, classDef); @@ -158,12 +167,11 @@ private static List createClassAnnotations(Service service) { return annotations; } - private static List createClassMethods( - TransportContext transportContext, Service service, TypeStore typeStore) { + private List createClassMethods(Service service, TypeStore typeStore) { List javaMethods = new ArrayList<>(); javaMethods.addAll(createSettingsGetterMethods(service, typeStore)); javaMethods.add(createCreatorMethod(service, typeStore)); - javaMethods.addAll(createDefaultGetterMethods(transportContext, service, typeStore)); + javaMethods.addAll(createDefaultGetterMethods(service, typeStore)); javaMethods.addAll(createBuilderHelperMethods(service, typeStore)); javaMethods.add(createConstructorMethod(service, typeStore)); return javaMethods; @@ -193,7 +201,8 @@ private static MethodDefinition createConstructorMethod(Service service, TypeSto } // TODO(miraleung): Consider merging this with createNestedBuilderSettingsGetterMethods. - private static List createSettingsGetterMethods(Service service, TypeStore typeStore) { + private static List createSettingsGetterMethods( + Service service, TypeStore typeStore) { TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); BiFunction methodMakerFn = (retType, javaMethodName) -> @@ -295,8 +304,7 @@ private static MethodDefinition createCreatorMethod(Service service, TypeStore t .build(); } - private static List createDefaultGetterMethods( - TransportContext transportContext, Service service, TypeStore typeStore) { + private List createDefaultGetterMethods(Service service, TypeStore typeStore) { BiFunction methodStarterFn = (mName, retType) -> MethodDefinition.builder() @@ -346,8 +354,8 @@ private static List createDefaultGetterMethods( javaMethods.add( methodMakerFn.apply( methodStarterFn.apply( - transportContext.defaultTransportProviderBuilderName(), - typeMakerFn.apply(transportContext.instantiatingChannelProviderClass())), + getTransportContext().defaultTransportProviderBuilderName(), + typeMakerFn.apply(getTransportContext().instantiatingChannelProviderClass())), SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT)); javaMethods.add( @@ -375,7 +383,8 @@ private static List createDefaultGetterMethods( return javaMethods; } - private static List createBuilderHelperMethods(Service service, TypeStore typeStore) { + private static List createBuilderHelperMethods( + Service service, TypeStore typeStore) { TypeNode builderType = typeStore.get(BUILDER_CLASS_NAME); MethodDefinition newBuilderMethodOne = MethodDefinition.builder() diff --git a/src/main/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java similarity index 67% rename from src/main/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java index 6c02c4c310..4b6e8555b1 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubClassComposer.java @@ -12,13 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.core.BackgroundResourceAggregation; -import com.google.api.gax.grpc.GrpcCallSettings; -import com.google.api.gax.grpc.GrpcStubCallableFactory; import com.google.api.gax.rpc.BidiStreamingCallable; import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.ClientStreamingCallable; @@ -27,13 +25,11 @@ import com.google.api.gax.rpc.ServerStreamingCallable; import com.google.api.gax.rpc.UnaryCallable; import com.google.api.generator.engine.ast.AnnotationNode; -import com.google.api.generator.engine.ast.AnonymousClassExpr; import com.google.api.generator.engine.ast.AssignmentExpr; import com.google.api.generator.engine.ast.ClassDefinition; import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.ConcreteReference; import com.google.api.generator.engine.ast.EmptyLineStatement; -import com.google.api.generator.engine.ast.EnumRefExpr; import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; import com.google.api.generator.engine.ast.JavaDocComment; @@ -43,7 +39,6 @@ import com.google.api.generator.engine.ast.ReferenceConstructorExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; -import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.ThisObjectValue; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; @@ -51,7 +46,6 @@ import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.gapic.composer.comment.StubCommentComposer; import com.google.api.generator.gapic.composer.store.TypeStore; -import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.composer.utils.PackageChecker; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; @@ -62,32 +56,24 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.longrunning.Operation; -import com.google.longrunning.stub.GrpcOperationsStub; -import io.grpc.MethodDescriptor; -import io.grpc.protobuf.ProtoUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Generated; -public class GrpcServiceStubClassComposer implements ClassComposer { +public abstract class AbstractServiceStubClassComposer implements ClassComposer { private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); - private static final String GRPC_SERVICE_CALLABLE_FACTORY_PATTERN = "Grpc%sCallableFactory"; private static final String METHOD_DESCRIPTOR_NAME_PATTERN = "%sMethodDescriptor"; private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; private static final String PAGED_CALLABLE_CLASS_MEMBER_PATTERN = "%sPagedCallable"; - private static final String STUB_SETTINGS_PATTERN = "%sStubSettings"; - private static final String STUB_PATTERN = "%sStub"; private static final String BACKGROUND_RESOURCES_MEMBER_NAME = "backgroundResources"; private static final String CALLABLE_NAME = "Callable"; @@ -98,32 +84,50 @@ public class GrpcServiceStubClassComposer implements ClassComposer { private static final String OPERATIONS_STUB_MEMBER_NAME = "operationsStub"; private static final String PAGED_CALLABLE_NAME = "PagedCallable"; - private static final GrpcServiceStubClassComposer INSTANCE = new GrpcServiceStubClassComposer(); + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); - private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + private final TransportContext transportContext; - // Legacy support for the original reroute_to_grpc_interface option in gapic.yaml. These two APIs - // predate the modern way, which is to add the RPCs directly into the proto. - private static final Set REROUTE_TO_GRPC_INTERFACE_SERVICE_ALLOWLIST = - new HashSet<>(Arrays.asList("google.pubsub.v1")); - private static final Set REROUTE_TO_GRPC_INTERFACE_IAM_METHOD_ALLOWLIST = - new HashSet<>(Arrays.asList("SetIamPolicy", "GetIamPolicy", "TestIamPermissions")); + protected AbstractServiceStubClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } - private GrpcServiceStubClassComposer() {} + public TransportContext getTransportContext() { + return transportContext; + } - public static GrpcServiceStubClassComposer instance() { - return INSTANCE; + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + BackgroundResource.class, + BackgroundResourceAggregation.class, + BetaApi.class, + BidiStreamingCallable.class, + ClientContext.class, + ClientStreamingCallable.class, + Generated.class, + ImmutableMap.class, + InterruptedException.class, + IOException.class, + Operation.class, + OperationCallable.class, + RequestParamsExtractor.class, + ServerStreamingCallable.class, + TimeUnit.class, + UnaryCallable.class); + return new TypeStore(concreteClazzes); } @Override - public GapicClass generate(GapicContext ignored, Service service) { + public GapicClass generate(GapicContext context, Service service) { String pakkage = service.pakkage() + ".stub"; TypeStore typeStore = createDynamicTypes(service, pakkage); - String className = ClassNames.getGrpcServiceStubClassName(service); + String className = getTransportContext().classNames().getTransportServiceStubClassName(service); GapicClass.Kind kind = Kind.STUB; Map protoMethodNameToDescriptorVarExprs = - createProtoMethodNameToDescriptorClassMembers(service); + createProtoMethodNameToDescriptorClassMembers( + service, getTransportContext().methodDescriptorClass()); Map callableClassMemberVarExprs = createCallableClassMembers(service, typeStore); @@ -136,19 +140,21 @@ public GapicClass generate(GapicContext ignored, Service service) { .setName(BACKGROUND_RESOURCES_MEMBER_NAME) .setType(FIXED_TYPESTORE.get("BackgroundResource")) .build())); - classMemberVarExprs.put( - OPERATIONS_STUB_MEMBER_NAME, - VariableExpr.withVariable( - Variable.builder() - .setName(OPERATIONS_STUB_MEMBER_NAME) - .setType(FIXED_TYPESTORE.get("GrpcOperationsStub")) - .build())); + if (getTransportContext().transportOperationsStubType() != null) { + classMemberVarExprs.put( + OPERATIONS_STUB_MEMBER_NAME, + VariableExpr.withVariable( + Variable.builder() + .setName(OPERATIONS_STUB_MEMBER_NAME) + .setType(getTransportContext().transportOperationsStubType()) + .build())); + } classMemberVarExprs.put( CALLABLE_FACTORY_MEMBER_NAME, VariableExpr.withVariable( Variable.builder() .setName(CALLABLE_FACTORY_MEMBER_NAME) - .setType(FIXED_TYPESTORE.get("GrpcStubCallableFactory")) + .setType(getTransportContext().stubCallableFactoryType()) .build())); List classStatements = @@ -158,16 +164,20 @@ public GapicClass generate(GapicContext ignored, Service service) { callableClassMemberVarExprs, classMemberVarExprs); + StubCommentComposer commentComposer = + new StubCommentComposer(getTransportContext().transportName()); + ClassDefinition classDef = ClassDefinition.builder() .setPackageString(pakkage) .setHeaderCommentStatements( - StubCommentComposer.createGrpcServiceStubClassHeaderComments( + commentComposer.createTransportServiceStubClassHeaderComments( service.name(), service.isDeprecated())) .setAnnotations(createClassAnnotations(service)) .setScope(ScopeNode.PUBLIC) .setName(className) - .setExtendsType(typeStore.get(ClassNames.getServiceStubClassName(service))) + .setExtendsType( + typeStore.get(getTransportContext().classNames().getServiceStubClassName(service))) .setStatements(classStatements) .setMethods( createClassMethods( @@ -180,7 +190,23 @@ public GapicClass generate(GapicContext ignored, Service service) { return GapicClass.create(kind, classDef); } - private static List createClassStatements( + protected abstract Statement createMethodDescriptorVariableDecl( + Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr); + + protected abstract List createOperationsStubGetterMethod( + VariableExpr operationsStubVarExpr); + + protected abstract Expr createTransportSettingsInitExpr( + Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr); + + protected List createGetMethodDescriptorsMethod( + Service service, + TypeStore typeStore, + Map protoMethodNameToDescriptorVarExprs) { + return Arrays.asList(); + } + + protected List createClassStatements( Service service, Map protoMethodNameToDescriptorVarExprs, Map callableClassMemberVarExprs, @@ -199,7 +225,7 @@ private static List createClassStatements( return classStatements; } - private static List createMethodDescriptorVariableDecls( + protected List createMethodDescriptorVariableDecls( Service service, Map protoMethodNameToDescriptorVarExprs) { return service.methods().stream() .map( @@ -209,86 +235,6 @@ private static List createMethodDescriptorVariableDecls( .collect(Collectors.toList()); } - private static Statement createMethodDescriptorVariableDecl( - Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr) { - MethodInvocationExpr methodDescriptorMaker = - MethodInvocationExpr.builder() - .setMethodName("newBuilder") - .setStaticReferenceType(FIXED_TYPESTORE.get("MethodDescriptor")) - .setGenerics(methodDescriptorVarExpr.variable().type().reference().generics()) - .build(); - - BiFunction> methodMakerFn = - (mName, argExpr) -> - m -> - MethodInvocationExpr.builder() - .setMethodName(mName) - .setArguments(Arrays.asList(argExpr)) - .setExprReferenceExpr(m) - .build(); - - methodDescriptorMaker = - methodMakerFn - .apply("setType", getMethodDescriptorMethodTypeExpr(protoMethod)) - .apply(methodDescriptorMaker); - - String codeMethodNameArg = getProtoRpcFullMethodName(service, protoMethod); - methodDescriptorMaker = - methodMakerFn - .apply( - "setFullMethodName", - ValueExpr.withValue(StringObjectValue.withValue(codeMethodNameArg))) - .apply(methodDescriptorMaker); - - Function protoUtilsMarshallerFn = - m -> - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ProtoUtils")) - .setMethodName("marshaller") - .setArguments(Arrays.asList(m)) - .build(); - MethodInvocationExpr methodInvocationArg = - MethodInvocationExpr.builder() - .setMethodName("getDefaultInstance") - .setStaticReferenceType(protoMethod.inputType()) - .build(); - - methodDescriptorMaker = - methodMakerFn - .apply("setRequestMarshaller", protoUtilsMarshallerFn.apply(methodInvocationArg)) - .apply(methodDescriptorMaker); - - methodInvocationArg = - MethodInvocationExpr.builder() - .setMethodName("getDefaultInstance") - .setStaticReferenceType(protoMethod.outputType()) - .build(); - methodDescriptorMaker = - methodMakerFn - .apply("setResponseMarshaller", protoUtilsMarshallerFn.apply(methodInvocationArg)) - .apply(methodDescriptorMaker); - - methodDescriptorMaker = - MethodInvocationExpr.builder() - .setMethodName("build") - .setExprReferenceExpr(methodDescriptorMaker) - .setReturnType(methodDescriptorVarExpr.type()) - .build(); - - return ExprStatement.withExpr( - AssignmentExpr.builder() - .setVariableExpr( - methodDescriptorVarExpr - .toBuilder() - .setIsDecl(true) - .setScope(ScopeNode.PRIVATE) - .setIsStatic(true) - .setIsFinal(true) - .build()) - .setValueExpr(methodDescriptorMaker) - .build()); - } - private static List createClassMemberFieldDeclarations( Map fieldNameToVarExprs) { return fieldNameToVarExprs.values().stream() @@ -303,12 +249,12 @@ private static List createClassMemberFieldDeclarations( .collect(Collectors.toList()); } - private static Map createProtoMethodNameToDescriptorClassMembers( - Service service) { + protected Map createProtoMethodNameToDescriptorClassMembers( + Service service, Class descriptorClass) { return service.methods().stream() .collect( Collectors.toMap( - m -> m.name(), + Method::name, m -> VariableExpr.withVariable( Variable.builder() @@ -319,7 +265,7 @@ private static Map createProtoMethodNameToDescriptorClassM .setType( TypeNode.withReference( ConcreteReference.builder() - .setClazz(MethodDescriptor.class) + .setClazz(descriptorClass) .setGenerics( Arrays.asList( m.inputType().reference(), @@ -328,7 +274,7 @@ private static Map createProtoMethodNameToDescriptorClassM .build()))); } - private static Map createCallableClassMembers( + private Map createCallableClassMembers( Service service, TypeStore typeStore) { Map callableClassMembers = new LinkedHashMap<>(); // Using a for-loop because the output cardinality is not a 1:1 mapping to the input set. @@ -388,7 +334,7 @@ private static Map createCallableClassMembers( return callableClassMembers; } - private static List createClassAnnotations(Service service) { + protected List createClassAnnotations(Service service) { List annotations = new ArrayList<>(); if (!PackageChecker.isGaApi(service.pakkage())) { annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); @@ -406,7 +352,7 @@ private static List createClassAnnotations(Service service) { return annotations; } - private static List createClassMethods( + protected List createClassMethods( Service service, TypeStore typeStore, Map classMemberVarExprs, @@ -421,7 +367,9 @@ private static List createClassMethods( classMemberVarExprs, callableClassMemberVarExprs, protoMethodNameToDescriptorVarExprs)); - javaMethods.add( + javaMethods.addAll( + createGetMethodDescriptorsMethod(service, typeStore, protoMethodNameToDescriptorVarExprs)); + javaMethods.addAll( createOperationsStubGetterMethod(classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME))); javaMethods.addAll(createCallableGetterMethods(callableClassMemberVarExprs)); javaMethods.addAll( @@ -429,10 +377,9 @@ private static List createClassMethods( return javaMethods; } - private static List createStaticCreatorMethods( - Service service, TypeStore typeStore) { + private List createStaticCreatorMethods(Service service, TypeStore typeStore) { TypeNode creatorMethodReturnType = - typeStore.get(ClassNames.getGrpcServiceStubClassName(service)); + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); Function, MethodDefinition.Builder> creatorMethodStarterFn = argList -> MethodDefinition.builder() @@ -453,7 +400,8 @@ private static List createStaticCreatorMethods( argList -> NewObjectExpr.builder().setType(creatorMethodReturnType).setArguments(argList).build(); - TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); VariableExpr settingsVarExpr = VariableExpr.withVariable( Variable.builder().setName("settings").setType(stubSettingsType).build()); @@ -467,7 +415,7 @@ private static List createStaticCreatorMethods( VariableExpr.withVariable( Variable.builder() .setName("callableFactory") - .setType(FIXED_TYPESTORE.get("GrpcStubCallableFactory")) + .setType(getTransportContext().stubCallableFactoryType()) .build()); MethodInvocationExpr clientContextCreateMethodExpr = @@ -509,13 +457,14 @@ private static List createStaticCreatorMethods( .build()); } - private static List createConstructorMethods( + protected List createConstructorMethods( Service service, TypeStore typeStore, Map classMemberVarExprs, Map callableClassMemberVarExprs, Map protoMethodNameToDescriptorVarExprs) { - TypeNode stubSettingsType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); + TypeNode stubSettingsType = + typeStore.get(getTransportContext().classNames().getServiceStubSettingsClassName(service)); VariableExpr settingsVarExpr = VariableExpr.withVariable( Variable.builder().setName("settings").setType(stubSettingsType).build()); @@ -529,10 +478,11 @@ private static List createConstructorMethods( VariableExpr.withVariable( Variable.builder() .setName("callableFactory") - .setType(FIXED_TYPESTORE.get("GrpcStubCallableFactory")) + .setType(getTransportContext().stubCallableFactoryType()) .build()); - TypeNode thisClassType = typeStore.get(ClassNames.getGrpcServiceStubClassName(service)); + TypeNode thisClassType = + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)); TypeNode ioExceptionType = TypeNode.withReference(ConcreteReference.withClazz(IOException.class)); @@ -564,40 +514,43 @@ private static List createConstructorMethods( NewObjectExpr.builder() .setType( typeStore.get( - ClassNames.getGrpcServiceCallableFactoryClassName(service))) + getTransportContext() + .classNames() + .getTransportServiceCallableFactoryClassName(service))) .build()) .build()))); Expr thisExpr = ValueExpr.withValue( ThisObjectValue.withType( - typeStore.get(ClassNames.getGrpcServiceStubClassName(service)))); + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service)))); // Body of the second constructor method. List secondCtorStatements = new ArrayList<>(); List secondCtorExprs = new ArrayList<>(); secondCtorExprs.add( AssignmentExpr.builder() .setVariableExpr( - classMemberVarExprs - .get("callableFactory") - .toBuilder() + classMemberVarExprs.get("callableFactory").toBuilder() .setExprReferenceExpr(thisExpr) .build()) .setValueExpr(callableFactoryVarExpr) .build()); - VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get("operationsStub"); - secondCtorExprs.add( - AssignmentExpr.builder() - .setVariableExpr( - operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GrpcOperationsStub")) - .setMethodName("create") - .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) - .setReturnType(operationsStubClassVarExpr.type()) - .build()) - .build()); + VariableExpr operationsStubClassVarExpr = classMemberVarExprs.get(OPERATIONS_STUB_MEMBER_NAME); + if (getTransportContext().transportOperationsStubType() != null) { + secondCtorExprs.add( + AssignmentExpr.builder() + .setVariableExpr( + operationsStubClassVarExpr.toBuilder().setExprReferenceExpr(thisExpr).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType( + getTransportContext().transportOperationsStubType()) + .setMethodName("create") + .setArguments(Arrays.asList(clientContextVarExpr, callableFactoryVarExpr)) + .setReturnType(operationsStubClassVarExpr.type()) + .build()) + .build()); + } secondCtorStatements.addAll( secondCtorExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); secondCtorExprs.clear(); @@ -619,7 +572,7 @@ private static List createConstructorMethods( .setType( TypeNode.withReference( ConcreteReference.builder() - .setClazz(GrpcCallSettings.class) + .setClazz(getTransportContext().callSettingsClass()) .setGenerics( Arrays.asList( m.inputType().reference(), @@ -692,147 +645,6 @@ private static List createConstructorMethods( return Arrays.asList(firstCtor, secondCtor); } - private static Expr createTransportSettingsInitExpr( - Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { - MethodInvocationExpr callSettingsBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GrpcCallSettings")) - .setGenerics(transportSettingsVarExpr.type().reference().generics()) - .setMethodName("newBuilder") - .build(); - callSettingsBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(callSettingsBuilderExpr) - .setMethodName("setMethodDescriptor") - .setArguments(Arrays.asList(methodDescriptorVarExpr)) - .build(); - - if (method.hasHttpBindings()) { - callSettingsBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(callSettingsBuilderExpr) - .setMethodName("setParamsExtractor") - .setArguments(createRequestParamsExtractorAnonClass(method)) - .build(); - } - - callSettingsBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(callSettingsBuilderExpr) - .setMethodName("build") - .setReturnType(transportSettingsVarExpr.type()) - .build(); - return AssignmentExpr.builder() - .setVariableExpr(transportSettingsVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(callSettingsBuilderExpr) - .build(); - } - - private static AnonymousClassExpr createRequestParamsExtractorAnonClass(Method method) { - Preconditions.checkState( - method.hasHttpBindings(), String.format("Method %s has no HTTP binding", method.name())); - - TypeNode paramsVarType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(ImmutableMap.Builder.class) - .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) - .build()); - VariableExpr paramsVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("params").setType(paramsVarType).build()); - VariableExpr reqeustVarExpr = - VariableExpr.withVariable( - Variable.builder().setName("request").setType(method.inputType()).build()); - - Expr paramsAssignExpr = - AssignmentExpr.builder() - .setVariableExpr(paramsVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ImmutableMap")) - .setMethodName("builder") - .setReturnType(paramsVarType) - .build()) - .build(); - List bodyExprs = new ArrayList<>(); - bodyExprs.add(paramsAssignExpr); - - VariableExpr requestVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(method.inputType()).setName("request").build()); - - for (String httpBindingFieldName : method.httpBindings()) { - // Handle foo.bar cases by descending into the subfields. - MethodInvocationExpr.Builder requestFieldGetterExprBuilder = - MethodInvocationExpr.builder().setExprReferenceExpr(requestVarExpr); - String[] descendantFields = httpBindingFieldName.split("\\."); - for (int i = 0; i < descendantFields.length; i++) { - String currFieldName = descendantFields[i]; - String bindingFieldMethodName = - String.format("get%s", JavaStyle.toUpperCamelCase(currFieldName)); - requestFieldGetterExprBuilder = - requestFieldGetterExprBuilder.setMethodName(bindingFieldMethodName); - if (i < descendantFields.length - 1) { - requestFieldGetterExprBuilder = - MethodInvocationExpr.builder() - .setExprReferenceExpr(requestFieldGetterExprBuilder.build()); - } - } - - MethodInvocationExpr requestBuilderExpr = requestFieldGetterExprBuilder.build(); - Expr valueOfExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(TypeNode.STRING) - .setMethodName("valueOf") - .setArguments(requestBuilderExpr) - .build(); - - Expr paramsPutExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(paramsVarExpr) - .setMethodName("put") - .setArguments( - ValueExpr.withValue(StringObjectValue.withValue(httpBindingFieldName)), - valueOfExpr) - .build(); - bodyExprs.add(paramsPutExpr); - } - - TypeNode returnType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(Map.class) - .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) - .build()); - Expr returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(paramsVarExpr) - .setMethodName("build") - .setReturnType(returnType) - .build(); - - MethodDefinition extractMethod = - MethodDefinition.builder() - .setIsOverride(true) - .setScope(ScopeNode.PUBLIC) - .setReturnType(returnType) - .setName("extract") - .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) - .setBody( - bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())) - .setReturnExpr(returnExpr) - .build(); - - TypeNode anonClassType = - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(RequestParamsExtractor.class) - .setGenerics(method.inputType().reference()) - .build()); - return AnonymousClassExpr.builder().setType(anonClassType).setMethods(extractMethod).build(); - } - private static Expr createCallableInitExpr( String callableVarName, VariableExpr callableVarExpr, @@ -924,16 +736,6 @@ private static String getCallableCreatorMethodName(TypeNode callableVarExprType) return String.format("create%sCallable", streamName); } - private static MethodDefinition createOperationsStubGetterMethod( - VariableExpr operationsStubVarExpr) { - return MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setReturnType(operationsStubVarExpr.type()) - .setName("getOperationsStub") - .setReturnExpr(operationsStubVarExpr) - .build(); - } - private static List createCallableGetterMethods( Map callableClassMemberVarExprs) { return callableClassMemberVarExprs.entrySet().stream() @@ -949,7 +751,7 @@ private static List createCallableGetterMethods( .collect(Collectors.toList()); } - private static List createStubOverrideMethods( + private List createStubOverrideMethods( VariableExpr backgroundResourcesVarExpr) { Function methodMakerStarterFn = methodName -> @@ -1033,42 +835,15 @@ private static List createStubOverrideMethods( return javaMethods; } - private static TypeStore createStaticTypes() { - List concreteClazzes = - Arrays.asList( - BackgroundResource.class, - BackgroundResourceAggregation.class, - BetaApi.class, - BidiStreamingCallable.class, - ClientContext.class, - ClientStreamingCallable.class, - Generated.class, - GrpcCallSettings.class, - GrpcOperationsStub.class, - GrpcStubCallableFactory.class, - ImmutableMap.class, - InterruptedException.class, - IOException.class, - MethodDescriptor.class, - Operation.class, - OperationCallable.class, - ProtoUtils.class, - RequestParamsExtractor.class, - ServerStreamingCallable.class, - TimeUnit.class, - UnaryCallable.class); - return new TypeStore(concreteClazzes); - } - - private static TypeStore createDynamicTypes(Service service, String stubPakkage) { + private TypeStore createDynamicTypes(Service service, String stubPakkage) { TypeStore typeStore = new TypeStore(); typeStore.putAll( stubPakkage, Arrays.asList( - ClassNames.getGrpcServiceStubClassName(service), - ClassNames.getServiceStubSettingsClassName(service), - ClassNames.getServiceStubClassName(service), - ClassNames.getGrpcServiceCallableFactoryClassName(service))); + getTransportContext().classNames().getTransportServiceStubClassName(service), + getTransportContext().classNames().getServiceStubSettingsClassName(service), + getTransportContext().classNames().getServiceStubClassName(service), + getTransportContext().classNames().getTransportServiceCallableFactoryClassName(service))); // Pagination types. typeStore.putAll( service.pakkage(), @@ -1077,7 +852,7 @@ private static TypeStore createDynamicTypes(Service service, String stubPakkage) .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) .collect(Collectors.toList()), true, - ClassNames.getServiceClientClassName(service)); + getTransportContext().classNames().getServiceClientClassName(service)); return typeStore; } @@ -1107,53 +882,22 @@ private static TypeNode getCallableType(Method protoMethod) { protoMethod.inputType().reference(), protoMethod.outputType().reference()))); } - private static EnumRefExpr getMethodDescriptorMethodTypeExpr(Method protoMethod) { - String enumName = ""; - switch (protoMethod.stream()) { - case CLIENT: - enumName = "CLIENT_STREAMING"; - break; - case SERVER: - enumName = "SERVER_STREAMING"; - break; - case BIDI: - enumName = "BIDI_STREAMING"; - break; - case NONE: - // Fall through. - default: - enumName = "UNARY"; - } - return EnumRefExpr.builder() - .setName(enumName) - .setType( - TypeNode.withReference( - ConcreteReference.builder().setClazz(MethodDescriptor.MethodType.class).build())) - .build(); - } - - private static String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { - if (protoMethod.isMixin()) { - return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); - } - - if (!REROUTE_TO_GRPC_INTERFACE_SERVICE_ALLOWLIST.contains(protoService.protoPakkage()) - || !REROUTE_TO_GRPC_INTERFACE_IAM_METHOD_ALLOWLIST.contains(protoMethod.name())) { - return String.format( - "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); - } - // This is meant to be a temporary workaround until the allow-listed services come up with a - // long-term solution. - return String.format("google.iam.v1.IAMPolicy/%s", protoMethod.name()); - } - - private static CommentStatement createProtectedCtorComment(Service service) { + private CommentStatement createProtectedCtorComment(Service service) { return CommentStatement.withComment( JavaDocComment.withComment( String.format( "Constructs an instance of %s, using the given settings. This is protected so that" + " it is easy to make a subclass, but otherwise, the static factory methods" + " should be preferred.", - ClassNames.getGrpcServiceStubClassName(service)))); + getTransportContext().classNames().getTransportServiceStubClassName(service)))); + } + + protected String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { + if (protoMethod.isMixin()) { + return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); + } + + return String.format( + "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java similarity index 92% rename from src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java index bc42060de9..fb2d350011 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.MonitoredResourceDescriptor; import com.google.api.core.ApiFunction; @@ -26,10 +26,6 @@ import com.google.api.gax.core.GaxProperties; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.grpc.GaxGrpcProperties; -import com.google.api.gax.grpc.GrpcTransportChannel; -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.api.gax.grpc.ProtoOperationTransformers; import com.google.api.gax.longrunning.OperationSnapshot; import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; import com.google.api.gax.retrying.RetrySettings; @@ -121,7 +117,7 @@ import javax.annotation.Nullable; import org.threeten.bp.Duration; -public class ServiceStubSettingsClassComposer implements ClassComposer { +public abstract class AbstractServiceStubSettingsClassComposer implements ClassComposer { private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); private static final String BATCHING_DESC_PATTERN = "%s_BATCHING_DESC"; @@ -139,14 +135,9 @@ public class ServiceStubSettingsClassComposer implements ClassComposer { private static final String SETTINGS_LITERAL = "Settings"; private static final String DOT = "."; - private static final String LEFT_BRACE = "{"; - private static final String RIGHT_BRACE = "}"; - private static final String SLASH = "/"; - private static final ServiceStubSettingsClassComposer INSTANCE = - new ServiceStubSettingsClassComposer(); + protected static final TypeStore FIXED_TYPESTORE = createStaticTypes(); - private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); private static final VariableExpr DEFAULT_SERVICE_SCOPES_VAR_EXPR = createDefaultServiceScopesVarExpr(); private static final VariableExpr NESTED_UNARY_METHOD_SETTINGS_BUILDERS_VAR_EXPR = @@ -156,10 +147,14 @@ public class ServiceStubSettingsClassComposer implements ClassComposer { private static final VariableExpr NESTED_RETRY_PARAM_DEFINITIONS_VAR_EXPR = createNestedRetryParamDefinitionsVarExpr(); - private ServiceStubSettingsClassComposer() {} + private final TransportContext transportContext; - public static ServiceStubSettingsClassComposer instance() { - return INSTANCE; + protected AbstractServiceStubSettingsClassComposer(TransportContext transportContext) { + this.transportContext = transportContext; + } + + public TransportContext getTransportContext() { + return transportContext; } @Override @@ -201,7 +196,14 @@ public GapicClass generate(GapicContext context, Service service) { return GapicClass.create(GapicClass.Kind.STUB, classDef); } - private static List createClassAnnotations(Service service) { + protected abstract MethodDefinition createDefaultTransportTransportProviderBuilderMethod(); + + protected abstract MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + Service service, TypeStore typeStore); + + public abstract MethodDefinition createDefaultTransportChannelProviderMethod(); + + private List createClassAnnotations(Service service) { List annotations = new ArrayList<>(); if (!PackageChecker.isGaApi(service.pakkage())) { annotations.add(AnnotationNode.withType(FIXED_TYPESTORE.get("BetaApi"))); @@ -246,7 +248,7 @@ private static List createClassHeaderComments( classType); } - private static TypeNode createExtendsType(Service service, TypeStore typeStore) { + private TypeNode createExtendsType(Service service, TypeStore typeStore) { TypeNode thisClassType = typeStore.get(ClassNames.getServiceStubSettingsClassName(service)); return TypeNode.withReference( FIXED_TYPESTORE @@ -763,7 +765,7 @@ private static Expr createPagedListResponseFactoryAssignExpr( .build(); } - private static List createClassMethods( + private List createClassMethods( Service service, Map methodSettingsMemberVarExprs, Set deprecatedSettingVarNames, @@ -803,12 +805,13 @@ private static List createMethodSettingsGetterMethods( .collect(Collectors.toList()); } - private static MethodDefinition createCreateStubMethod(Service service, TypeStore typeStore) { + private MethodDefinition createCreateStubMethod(Service service, TypeStore typeStore) { // Set up the if-statement. - Expr grpcTransportNameExpr = + Expr tRansportNameExpr = MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GrpcTransportChannel")) - .setMethodName("getGrpcTransportName") + .setStaticReferenceType( + getTransportContext().transportChannelType()) + .setMethodName(getTransportContext().transportGetterName()) .build(); Expr getTransportNameExpr = @@ -823,13 +826,14 @@ private static MethodDefinition createCreateStubMethod(Service service, TypeStor MethodInvocationExpr.builder() .setExprReferenceExpr(getTransportNameExpr) .setMethodName("equals") - .setArguments(grpcTransportNameExpr) + .setArguments(tRansportNameExpr) .setReturnType(TypeNode.BOOLEAN) .build(); Expr createExpr = MethodInvocationExpr.builder() - .setStaticReferenceType(typeStore.get(ClassNames.getGrpcServiceStubClassName(service))) + .setStaticReferenceType( + typeStore.get(getTransportContext().classNames().getTransportServiceStubClassName(service))) .setMethodName("create") .setArguments( ValueExpr.withValue( @@ -877,7 +881,7 @@ private static MethodDefinition createCreateStubMethod(Service service, TypeStor .build(); } - private static List createDefaultHelperAndGetterMethods( + private List createDefaultHelperAndGetterMethods( Service service, TypeStore typeStore) { List javaMethods = new ArrayList<>(); @@ -959,123 +963,14 @@ private static List createDefaultHelperAndGetterMethods( .setReturnExpr(credsProviderBuilderExpr) .build()); - // Create the defaultGrpcTransportProviderBuilder method. - returnType = - TypeNode.withReference( - ConcreteReference.withClazz(InstantiatingGrpcChannelProvider.Builder.class)); - MethodInvocationExpr grpcChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("InstantiatingGrpcChannelProvider")) - .setMethodName("newBuilder") - .build(); - grpcChannelProviderBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(grpcChannelProviderBuilderExpr) - .setMethodName("setMaxInboundMessageSize") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) - .setStaticReferenceType(TypeNode.INT_OBJECT) - .build()) - .setReturnType(returnType) - .build(); - javaMethods.add( - MethodDefinition.builder() - .setHeaderCommentStatements( - SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultGrpcTransportProviderBuilder") - .setReturnExpr(grpcChannelProviderBuilderExpr) - .build()); - - // Create the defaultTransportChannelProvider method. - returnType = FIXED_TYPESTORE.get("TransportChannelProvider"); - MethodInvocationExpr transportProviderBuilderExpr = - MethodInvocationExpr.builder().setMethodName("defaultGrpcTransportProviderBuilder").build(); - transportProviderBuilderExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(transportProviderBuilderExpr) - .setMethodName("build") - .setReturnType(returnType) - .build(); - javaMethods.add( - MethodDefinition.builder() - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultTransportChannelProvider") - .setReturnExpr(transportProviderBuilderExpr) - .build()); - - // Create the defaultApiClientHeaderProviderBuilder method. - returnType = - TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); - MethodInvocationExpr returnExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) - .setMethodName("newBuilder") - .build(); - - MethodInvocationExpr versionArgExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) - .setMethodName("getLibraryVersion") - .setArguments( - VariableExpr.builder() - .setVariable( - Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) - .setStaticReferenceType( - typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) - .build()) - .build(); - - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setGeneratedLibToken") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) - .build(); - returnExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(returnExpr) - .setMethodName("setTransportToken") - .setArguments( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxGrpcProperties")) - .setMethodName("getGrpcTokenName") - .build(), - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxGrpcProperties")) - .setMethodName("getGrpcVersion") - .build()) - .setReturnType(returnType) - .build(); - - AnnotationNode annotation = - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("BetaApi")) - .setDescription( - "The surface for customizing headers is not stable yet and may change in the" - + " future.") - .build(); - javaMethods.add( - MethodDefinition.builder() - .setAnnotations(Arrays.asList(annotation)) - .setScope(ScopeNode.PUBLIC) - .setIsStatic(true) - .setReturnType(returnType) - .setName("defaultApiClientHeaderProviderBuilder") - .setReturnExpr(returnExpr) - .build()); + javaMethods.add(createDefaultTransportTransportProviderBuilderMethod()); + javaMethods.add(createDefaultTransportChannelProviderMethod()); + javaMethods.add(createDefaultApiClientHeaderProviderBuilderMethod(service, typeStore)); return javaMethods; } - private static List createBuilderHelperMethods( - Service service, TypeStore typeStore) { + private static List createBuilderHelperMethods(Service service, TypeStore typeStore) { List javaMethods = new ArrayList<>(); // Create the newBuilder() method. final TypeNode builderReturnType = typeStore.get(NESTED_BUILDER_CLASS_NAME); @@ -1857,17 +1752,14 @@ private static TypeStore createStaticTypes() { Duration.class, Empty.class, FlowControlSettings.class, - GaxGrpcProperties.class, GaxProperties.class, Generated.class, GoogleCredentialsProvider.class, - GrpcTransportChannel.class, IOException.class, ImmutableList.class, ImmutableMap.class, ImmutableSet.class, InstantiatingExecutorProvider.class, - InstantiatingGrpcChannelProvider.class, LimitExceededBehavior.class, List.class, Lists.class, @@ -1881,7 +1773,6 @@ private static TypeStore createStaticTypes() { PagedListDescriptor.class, PagedListResponseFactory.class, PartitionKey.class, - ProtoOperationTransformers.class, RequestBuilder.class, RetrySettings.class, ServerStreamingCallSettings.class, @@ -1894,7 +1785,7 @@ private static TypeStore createStaticTypes() { return new TypeStore(concreteClazzes); } - private static TypeStore createDynamicTypes(Service service, String pakkage) { + private TypeStore createDynamicTypes(Service service, String pakkage) { TypeStore typeStore = new TypeStore(); // This type. @@ -1903,7 +1794,7 @@ private static TypeStore createDynamicTypes(Service service, String pakkage) { pakkage, Arrays.asList( thisClassName, - ClassNames.getGrpcServiceStubClassName(service), + getTransportContext().classNames().getTransportServiceStubClassName(service), ClassNames.getServiceStubSettingsClassName(service), ClassNames.getServiceStubClassName(service))); diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/BUILD.bazel b/src/main/java/com/google/api/generator/gapic/composer/common/BUILD.bazel index be2ec575c3..8423f4ff78 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/BUILD.bazel +++ b/src/main/java/com/google/api/generator/gapic/composer/common/BUILD.bazel @@ -14,6 +14,7 @@ java_library( ], deps = [ "//:service_config_java_proto", + "//src/main/java/com/google/api/generator:autovalue", "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/engine/writer", "//src/main/java/com/google/api/generator/gapic:status_java_proto", @@ -27,10 +28,12 @@ java_library( "//src/main/java/com/google/api/generator/gapic/utils", "//src/main/java/com/google/api/generator/util", "@com_google_api_api_common//jar", - "@com_google_api_gax_java//gax:gax", + "@com_google_api_gax_java//gax", "@com_google_api_gax_java//gax:gax_testlib", "@com_google_api_gax_java//gax-grpc:gax_grpc", "@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", + "@com_google_auto_value_auto_value//jar", + "@com_google_auto_value_auto_value_annotations//jar", "@com_google_code_findbugs_jsr305//jar", "@com_google_googleapis//gapic/metadata:metadata_java_proto", "@com_google_googleapis//google/api:api_java_proto", diff --git a/src/main/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposer.java similarity index 99% rename from src/main/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposer.java index c89eef053c..8de7d4c9c2 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.gax.batching.PartitionKey; import com.google.api.gax.batching.RequestBuilder; diff --git a/src/main/java/com/google/api/generator/gapic/composer/common/ClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/ClassComposer.java index 5ebb6ca31e..d8d87eadc1 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/common/ClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/ClassComposer.java @@ -18,7 +18,6 @@ import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; -// TODO: remove after Pre-DIREGAPIC refactoring is fully merged public interface ClassComposer { GapicClass generate(GapicContext context, Service serivce); } diff --git a/src/main/java/com/google/api/generator/gapic/composer/RetrySettingsComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java similarity index 99% rename from src/main/java/com/google/api/generator/gapic/composer/RetrySettingsComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java index 77253189d2..4a20961399 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/RetrySettingsComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.batching.FlowControlSettings; diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java similarity index 99% rename from src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java index 67b41d6938..97cf85f5ad 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java similarity index 99% rename from src/main/java/com/google/api/generator/gapic/composer/ServiceStubClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java index 697de66cc3..9d16f98f88 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceStubClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.core.BetaApi; import com.google.api.gax.core.BackgroundResource; diff --git a/src/main/java/com/google/api/generator/gapic/model/TransportContext.java b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java similarity index 88% rename from src/main/java/com/google/api/generator/gapic/model/TransportContext.java rename to src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java index c88cfadc69..4058fbafbf 100644 --- a/src/main/java/com/google/api/generator/gapic/model/TransportContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/common/TransportContext.java @@ -12,33 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.model; +package com.google.api.generator.gapic.composer.common; import com.google.api.generator.engine.ast.ConcreteReference; import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Transport; import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; @AutoValue public abstract class TransportContext { - public enum Transport { - REST, - GRPC, - GRPC_REST; - - public static Transport parse(String name) { - return valueOf(name.replace('+', '_').toUpperCase()); - } - } + + public abstract ClassNames classNames(); // For AbstractServiceStubClassComposer public abstract Transport transport(); + public abstract String transportName(); + public abstract Class callSettingsClass(); public abstract TypeNode stubCallableFactoryType(); public abstract Class methodDescriptorClass(); + @Nullable public abstract TypeNode transportOperationsStubType(); // For AbstractServiceSettingsClassComposer @@ -70,8 +69,13 @@ public static TransportContext.Builder builder() { @AutoValue.Builder public abstract static class Builder { + + public abstract Builder setClassNames(ClassNames value); + public abstract Builder setTransport(Transport transport); + public abstract Builder setTransportName(String value); + public abstract Builder setCallSettingsClass(Class callSettingsClass); public abstract Builder setStubCallableFactoryType(TypeNode stubCallableFactoryType); diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java index 494e0ffd8f..13623cfb5b 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcContext.java @@ -19,7 +19,9 @@ import com.google.api.gax.grpc.GrpcStubCallableFactory; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.api.generator.gapic.model.TransportContext; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Transport; +import com.google.api.generator.gapic.composer.common.TransportContext; import com.google.longrunning.stub.GrpcOperationsStub; import com.google.longrunning.stub.OperationsStub; import io.grpc.MethodDescriptor; @@ -27,7 +29,9 @@ public abstract class GrpcContext extends TransportContext { private static final TransportContext INSTANCE = GrpcContext.builder() + .setClassNames(new ClassNames("Grpc")) .setTransport(Transport.GRPC) + .setTransportName("gRPC") // For grpc.GrpcServiceStubClassComposer .setCallSettingsClass(GrpcCallSettings.class) .setStubCallableFactoryType(classToType(GrpcStubCallableFactory.class)) diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java new file mode 100644 index 0000000000..5698f5a443 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposer.java @@ -0,0 +1,179 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpc; + +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.gapic.composer.common.AbstractServiceCallableFactoryClassComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.longrunning.Operation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class GrpcServiceCallableFactoryClassComposer + extends AbstractServiceCallableFactoryClassComposer { + private static final GrpcServiceCallableFactoryClassComposer INSTANCE = + new GrpcServiceCallableFactoryClassComposer(); + private static final TypeNode OPERATION_TYPE = + TypeNode.withReference(ConcreteReference.withClazz(Operation.class)); + + protected GrpcServiceCallableFactoryClassComposer() { + super(GrpcContext.instance()); + } + + public static GrpcServiceCallableFactoryClassComposer instance() { + return INSTANCE; + } + + @Override + protected List createClassImplements(TypeStore typeStore) { + return Arrays.asList(getTransportContext().stubCallableFactoryType()); + } + + protected List createClassMethods(TypeStore typeStore) { + List classMethods = new ArrayList<>(super.createClassMethods(typeStore)); + classMethods.addAll( + Arrays.asList( + createBidiStreamingCallableMethod(typeStore), + createServerStreamingCallableMethod(typeStore), + createClientStreamingCallableMethod(typeStore))); + return classMethods; + } + + protected MethodDefinition createUnaryCallableMethod(TypeStore typeStore) { + String methodVariantName = "Unary"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList()), + /*callSettingsVariantName=*/ methodVariantName, + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } + + protected MethodDefinition createPagedCallableMethod(TypeStore typeStore) { + String methodVariantName = "Paged"; + String requestTemplateName = "RequestT"; + String pagedResponseTemplateName = "PagedListResponseT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = + Arrays.asList(requestTemplateName, responseTemplateName, pagedResponseTemplateName); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ "Unary", + /*returnCallableTemplateNames=*/ Arrays.asList( + requestTemplateName, pagedResponseTemplateName), + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ Arrays.asList( + requestTemplateName, responseTemplateName), + /*callSettingsVariantName=*/ methodVariantName, + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } + + @Override + protected MethodDefinition createOperationCallableMethod(TypeStore typeStore) { + String methodVariantName = "Operation"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = + Arrays.asList(requestTemplateName, responseTemplateName, "MetadataT"); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ Arrays.asList(requestTemplateName, OPERATION_TYPE), + /*callSettingsVariantName=*/ methodVariantName, + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } + + private MethodDefinition createBidiStreamingCallableMethod(TypeStore typeStore) { + String methodVariantName = "BidiStreaming"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList()), + /*callSettingsVariantName=*/ "Streaming", + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } + + private MethodDefinition createServerStreamingCallableMethod(TypeStore typeStore) { + String methodVariantName = "ServerStreaming"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList()), + /*callSettingsVariantName=*/ methodVariantName, + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } + + private MethodDefinition createClientStreamingCallableMethod(TypeStore typeStore) { + String methodVariantName = "ClientStreaming"; + String requestTemplateName = "RequestT"; + String responseTemplateName = "ResponseT"; + List methodTemplateNames = Arrays.asList(requestTemplateName, responseTemplateName); + return createGenericCallableMethod( + typeStore, + /*methodTemplateNames=*/ methodTemplateNames, + /*returnCallableKindName=*/ methodVariantName, + /*returnCallableTemplateNames=*/ methodTemplateNames, + /*methodVariantName=*/ methodVariantName, + /*grpcCallSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList()), + /*callSettingsVariantName=*/ "Streaming", + /*callSettingsTemplateObjects=*/ methodTemplateNames.stream() + .map(n -> (Object) n) + .collect(Collectors.toList())); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java new file mode 100644 index 0000000000..e7b30ebcbe --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposer.java @@ -0,0 +1,362 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpc; + +import com.google.api.gax.grpc.GrpcCallSettings; +import com.google.api.gax.grpc.GrpcStubCallableFactory; +import com.google.api.gax.rpc.RequestParamsExtractor; +import com.google.api.generator.engine.ast.AnonymousClassExpr; +import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.EnumRefExpr; +import com.google.api.generator.engine.ast.Expr; +import com.google.api.generator.engine.ast.ExprStatement; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.Statement; +import com.google.api.generator.engine.ast.StringObjectValue; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubClassComposer; +import com.google.api.generator.gapic.composer.comment.StubCommentComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Method; +import com.google.api.generator.gapic.model.Service; +import com.google.api.generator.gapic.utils.JavaStyle; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.longrunning.stub.GrpcOperationsStub; +import io.grpc.MethodDescriptor; +import io.grpc.protobuf.ProtoUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class GrpcServiceStubClassComposer extends AbstractServiceStubClassComposer { + private static final GrpcServiceStubClassComposer INSTANCE = new GrpcServiceStubClassComposer(); + + // Legacy support for the original reroute_to_grpc_interface option in gapic.yaml. These two APIs + // predate the modern way, which is to add the RPCs directly into the proto. + private static final Set REROUTE_TO_GRPC_INTERFACE_SERVICE_ALLOWLIST = + new HashSet<>(Arrays.asList("google.pubsub.v1")); + private static final Set REROUTE_TO_GRPC_INTERFACE_IAM_METHOD_ALLOWLIST = + new HashSet<>(Arrays.asList("SetIamPolicy", "GetIamPolicy", "TestIamPermissions")); + + private static final TypeStore FIXED_GRPC_TYPE_STORE = createStaticTypes(); + + protected GrpcServiceStubClassComposer() { + super(GrpcContext.instance()); + } + + public static GrpcServiceStubClassComposer instance() { + return INSTANCE; + } + + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + GrpcCallSettings.class, + GrpcOperationsStub.class, + GrpcStubCallableFactory.class, + MethodDescriptor.class, + ProtoUtils.class); + return new TypeStore(concreteClazzes); + } + + @Override + protected Statement createMethodDescriptorVariableDecl( + Service service, Method protoMethod, VariableExpr methodDescriptorVarExpr) { + MethodInvocationExpr methodDescriptorMaker = + MethodInvocationExpr.builder() + .setMethodName("newBuilder") + .setStaticReferenceType(FIXED_GRPC_TYPE_STORE.get("MethodDescriptor")) + .setGenerics(methodDescriptorVarExpr.variable().type().reference().generics()) + .build(); + + BiFunction> methodMakerFn = + (mName, argExpr) -> + m -> + MethodInvocationExpr.builder() + .setMethodName(mName) + .setArguments(Arrays.asList(argExpr)) + .setExprReferenceExpr(m) + .build(); + + methodDescriptorMaker = + methodMakerFn + .apply("setType", getMethodDescriptorMethodTypeExpr(protoMethod)) + .apply(methodDescriptorMaker); + + String codeMethodNameArg = getProtoRpcFullMethodName(service, protoMethod); + methodDescriptorMaker = + methodMakerFn + .apply( + "setFullMethodName", + ValueExpr.withValue(StringObjectValue.withValue(codeMethodNameArg))) + .apply(methodDescriptorMaker); + + Function protoUtilsMarshallerFn = + m -> + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_GRPC_TYPE_STORE.get("ProtoUtils")) + .setMethodName("marshaller") + .setArguments(Arrays.asList(m)) + .build(); + MethodInvocationExpr methodInvocationArg = + MethodInvocationExpr.builder() + .setMethodName("getDefaultInstance") + .setStaticReferenceType(protoMethod.inputType()) + .build(); + + methodDescriptorMaker = + methodMakerFn + .apply("setRequestMarshaller", protoUtilsMarshallerFn.apply(methodInvocationArg)) + .apply(methodDescriptorMaker); + + methodInvocationArg = + MethodInvocationExpr.builder() + .setMethodName("getDefaultInstance") + .setStaticReferenceType(protoMethod.outputType()) + .build(); + methodDescriptorMaker = + methodMakerFn + .apply("setResponseMarshaller", protoUtilsMarshallerFn.apply(methodInvocationArg)) + .apply(methodDescriptorMaker); + + methodDescriptorMaker = + MethodInvocationExpr.builder() + .setMethodName("build") + .setExprReferenceExpr(methodDescriptorMaker) + .setReturnType(methodDescriptorVarExpr.type()) + .build(); + + return ExprStatement.withExpr( + AssignmentExpr.builder() + .setVariableExpr( + methodDescriptorVarExpr.toBuilder() + .setIsDecl(true) + .setScope(ScopeNode.PRIVATE) + .setIsStatic(true) + .setIsFinal(true) + .build()) + .setValueExpr(methodDescriptorMaker) + .build()); + } + + protected EnumRefExpr getMethodDescriptorMethodTypeExpr(Method protoMethod) { + String enumName = ""; + switch (protoMethod.stream()) { + case CLIENT: + enumName = "CLIENT_STREAMING"; + break; + case SERVER: + enumName = "SERVER_STREAMING"; + break; + case BIDI: + enumName = "BIDI_STREAMING"; + break; + case NONE: + // Fall through. + default: + enumName = "UNARY"; + } + return EnumRefExpr.builder() + .setName(enumName) + .setType( + TypeNode.withReference( + ConcreteReference.builder().setClazz(MethodDescriptor.MethodType.class).build())) + .build(); + } + + @Override + protected List createOperationsStubGetterMethod( + VariableExpr operationsStubVarExpr) { + return Arrays.asList( + MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setReturnType(operationsStubVarExpr.type()) + .setName("getOperationsStub") + .setReturnExpr(operationsStubVarExpr) + .build()); + } + + @Override + protected Expr createTransportSettingsInitExpr( + Method method, VariableExpr transportSettingsVarExpr, VariableExpr methodDescriptorVarExpr) { + MethodInvocationExpr callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(getTransportContext().transportCallSettingsType()) + .setGenerics(transportSettingsVarExpr.type().reference().generics()) + .setMethodName("newBuilder") + .build(); + callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callSettingsBuilderExpr) + .setMethodName("setMethodDescriptor") + .setArguments(Arrays.asList(methodDescriptorVarExpr)) + .build(); + + if (method.hasHttpBindings()) { + callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callSettingsBuilderExpr) + .setMethodName("setParamsExtractor") + .setArguments(createRequestParamsExtractorAnonClass(method)) + .build(); + } + + callSettingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(callSettingsBuilderExpr) + .setMethodName("build") + .setReturnType(transportSettingsVarExpr.type()) + .build(); + return AssignmentExpr.builder() + .setVariableExpr(transportSettingsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(callSettingsBuilderExpr) + .build(); + } + + @Override + protected String getProtoRpcFullMethodName(Service protoService, Method protoMethod) { + if (protoMethod.isMixin()) { + return String.format("%s/%s", protoMethod.mixedInApiName(), protoMethod.name()); + } + + if (!REROUTE_TO_GRPC_INTERFACE_SERVICE_ALLOWLIST.contains(protoService.protoPakkage()) + || !REROUTE_TO_GRPC_INTERFACE_IAM_METHOD_ALLOWLIST.contains(protoMethod.name())) { + return String.format( + "%s.%s/%s", protoService.protoPakkage(), protoService.name(), protoMethod.name()); + } + // This is meant to be a temporary workaround until the allow-listed services come up with a + // long-term solution. + return String.format("google.iam.v1.IAMPolicy/%s", protoMethod.name()); + } + + private AnonymousClassExpr createRequestParamsExtractorAnonClass(Method method) { + Preconditions.checkState( + method.hasHttpBindings(), String.format("Method %s has no HTTP binding", method.name())); + + TypeNode paramsVarType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(ImmutableMap.Builder.class) + .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) + .build()); + VariableExpr paramsVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("params").setType(paramsVarType).build()); + VariableExpr reqeustVarExpr = + VariableExpr.withVariable( + Variable.builder().setName("request").setType(method.inputType()).build()); + + Expr paramsAssignExpr = + AssignmentExpr.builder() + .setVariableExpr(paramsVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("ImmutableMap")) + .setMethodName("builder") + .setReturnType(paramsVarType) + .build()) + .build(); + List bodyExprs = new ArrayList<>(); + bodyExprs.add(paramsAssignExpr); + + VariableExpr requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + + for (String httpBindingFieldName : method.httpBindings()) { + // Handle foo.bar cases by descending into the subfields. + MethodInvocationExpr.Builder requestFieldGetterExprBuilder = + MethodInvocationExpr.builder().setExprReferenceExpr(requestVarExpr); + String[] descendantFields = httpBindingFieldName.split("\\."); + for (int i = 0; i < descendantFields.length; i++) { + String currFieldName = descendantFields[i]; + String bindingFieldMethodName = + String.format("get%s", JavaStyle.toUpperCamelCase(currFieldName)); + requestFieldGetterExprBuilder = + requestFieldGetterExprBuilder.setMethodName(bindingFieldMethodName); + if (i < descendantFields.length - 1) { + requestFieldGetterExprBuilder = + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestFieldGetterExprBuilder.build()); + } + } + + MethodInvocationExpr requestBuilderExpr = requestFieldGetterExprBuilder.build(); + Expr valueOfExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(TypeNode.STRING) + .setMethodName("valueOf") + .setArguments(requestBuilderExpr) + .build(); + + Expr paramsPutExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(paramsVarExpr) + .setMethodName("put") + .setArguments( + ValueExpr.withValue(StringObjectValue.withValue(httpBindingFieldName)), + valueOfExpr) + .build(); + bodyExprs.add(paramsPutExpr); + } + + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(Map.class) + .setGenerics(TypeNode.STRING.reference(), TypeNode.STRING.reference()) + .build()); + Expr returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(paramsVarExpr) + .setMethodName("build") + .setReturnType(returnType) + .build(); + + MethodDefinition extractMethod = + MethodDefinition.builder() + .setIsOverride(true) + .setScope(ScopeNode.PUBLIC) + .setReturnType(returnType) + .setName("extract") + .setArguments(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setBody( + bodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())) + .setReturnExpr(returnExpr) + .build(); + + TypeNode anonClassType = + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(RequestParamsExtractor.class) + .setGenerics(method.inputType().reference()) + .build()); + return AnonymousClassExpr.builder().setType(anonClassType).setMethods(extractMethod).build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/MockServiceClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposer.java similarity index 98% rename from src/main/java/com/google/api/generator/gapic/composer/MockServiceClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposer.java index c542153cf7..f1ac25fd06 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/MockServiceClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.core.BetaApi; import com.google.api.generator.engine.ast.AnnotationNode; @@ -29,6 +29,7 @@ import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.ClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.GapicClass; diff --git a/src/main/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposer.java similarity index 99% rename from src/main/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposer.java index 20b1f3f71e..a58601197d 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.core.BetaApi; import com.google.api.generator.engine.ast.AnnotationNode; @@ -39,6 +39,7 @@ import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.ClassComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.GapicClass; diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java similarity index 53% rename from src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java rename to src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java index f7315fe9e3..8d06bd29a9 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposer.java @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,57 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; -import com.google.api.gax.core.GoogleCredentialsProvider; -import com.google.api.gax.core.InstantiatingExecutorProvider; -import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GaxGrpcProperties; -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.api.gax.rpc.ApiClientHeaderProvider; -import com.google.api.gax.rpc.ApiStreamObserver; -import com.google.api.gax.rpc.BidiStreamingCallable; -import com.google.api.gax.rpc.ClientStreamingCallable; -import com.google.api.gax.rpc.InvalidArgumentException; -import com.google.api.gax.rpc.OperationCallSettings; -import com.google.api.gax.rpc.PagedCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallSettings; -import com.google.api.gax.rpc.ServerStreamingCallable; +import com.google.api.gax.grpc.testing.LocalChannelProvider; +import com.google.api.gax.grpc.testing.MockGrpcService; +import com.google.api.gax.grpc.testing.MockServiceHelper; +import com.google.api.gax.grpc.testing.MockStreamObserver; import com.google.api.gax.rpc.StatusCode; -import com.google.api.gax.rpc.StreamingCallSettings; -import com.google.api.gax.rpc.UnaryCallSettings; import com.google.api.generator.engine.ast.AnnotationNode; import com.google.api.generator.engine.ast.AssignmentExpr; import com.google.api.generator.engine.ast.CastExpr; -import com.google.api.generator.engine.ast.ClassDefinition; -import com.google.api.generator.engine.ast.CommentStatement; import com.google.api.generator.engine.ast.ConcreteReference; -import com.google.api.generator.engine.ast.EmptyLineStatement; import com.google.api.generator.engine.ast.EnumRefExpr; import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.ast.ExprStatement; import com.google.api.generator.engine.ast.InstanceofExpr; -import com.google.api.generator.engine.ast.LineComment; import com.google.api.generator.engine.ast.MethodDefinition; import com.google.api.generator.engine.ast.MethodInvocationExpr; import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.PrimitiveValue; -import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; import com.google.api.generator.engine.ast.StringObjectValue; import com.google.api.generator.engine.ast.TryCatchStatement; import com.google.api.generator.engine.ast.TypeNode; import com.google.api.generator.engine.ast.ValueExpr; -import com.google.api.generator.engine.ast.VaporReference; import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceClientTestClassComposer; import com.google.api.generator.gapic.composer.defaultvalue.DefaultValueComposer; import com.google.api.generator.gapic.composer.store.TypeStore; import com.google.api.generator.gapic.composer.utils.ClassNames; import com.google.api.generator.gapic.model.Field; -import com.google.api.generator.gapic.model.GapicClass; -import com.google.api.generator.gapic.model.GapicClass.Kind; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.Method; @@ -71,48 +53,28 @@ import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.utils.JavaStyle; import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.longrunning.Operation; +import com.google.common.collect.ImmutableMap; import com.google.protobuf.AbstractMessage; -import com.google.protobuf.Any; import io.grpc.StatusRuntimeException; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; -import javax.annotation.Generated; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -public class ServiceClientTestClassComposer implements ClassComposer { - private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create(); - - private static final String CHANNEL_PROVIDER_VAR_NAME = "channelProvider"; - private static final String CLASS_NAME_PATTERN = "%sClientTest"; - private static final String CLIENT_VAR_NAME = "client"; - private static final String GRPC_TESTING_PACKAGE = "com.google.api.gax.grpc.testing"; - private static final String MOCK_SERVICE_VAR_NAME_PATTERN = "mock%s"; - private static final String PAGED_RESPONSE_TYPE_NAME_PATTERN = "%sPagedResponse"; +public class ServiceClientTestClassComposer extends AbstractServiceClientTestClassComposer { private static final String SERVICE_HELPER_VAR_NAME = "mockServiceHelper"; - private static final String STUB_SETTINGS_PATTERN = "%sSettings"; + private static final String CHANNEL_PROVIDER_VAR_NAME = "channelProvider"; private static final ServiceClientTestClassComposer INSTANCE = new ServiceClientTestClassComposer(); - private static final TypeStore FIXED_TYPESTORE = createStaticTypes(); + protected static final TypeStore FIXED_GRPC_TYPESTORE = createStaticTypes(); + private static final TypeNode LIST_TYPE = TypeNode.withReference(ConcreteReference.withClazz(List.class)); private static final TypeNode MAP_TYPE = @@ -121,54 +83,34 @@ public class ServiceClientTestClassComposer implements ClassComposer { TypeNode.withReference( ConcreteReference.withClazz(com.google.api.resourcenames.ResourceName.class)); - private static final AnnotationNode TEST_ANNOTATION = - AnnotationNode.withType(FIXED_TYPESTORE.get("Test")); // Avoid conflicting types with com.google.rpc.Status. private static final TypeNode GRPC_STATUS_TYPE = TypeNode.withReference( ConcreteReference.builder().setClazz(io.grpc.Status.class).setUseFullName(true).build()); - private ServiceClientTestClassComposer() {} + protected ServiceClientTestClassComposer() { + super(GrpcContext.instance()); + } - public static ServiceClientTestClassComposer instance() { + public static AbstractServiceClientTestClassComposer instance() { return INSTANCE; } - @Override - public GapicClass generate(GapicContext context, Service service) { - Map resourceNames = context.helperResourceNames(); - Map messageTypes = context.messages(); - String pakkage = service.pakkage(); - TypeStore typeStore = new TypeStore(); - addDynamicTypes(context, service, typeStore); - String className = ClassNames.getServiceClientTestClassName(service); - GapicClass.Kind kind = Kind.MAIN; - - Map classMemberVarExprs = - createClassMemberVarExprs(service, context, typeStore); - - ClassDefinition classDef = - ClassDefinition.builder() - .setPackageString(pakkage) - .setAnnotations(createClassAnnotations()) - .setScope(ScopeNode.PUBLIC) - .setName(className) - .setStatements(createClassMemberFieldDecls(classMemberVarExprs)) - .setMethods( - createClassMethods(service, context, classMemberVarExprs, typeStore, resourceNames)) - .build(); - return GapicClass.create(kind, classDef); - } + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + GaxGrpcProperties.class, + LocalChannelProvider.class, + MockGrpcService.class, + MockServiceHelper.class, + MockStreamObserver.class, + StatusRuntimeException.class); - private static List createClassAnnotations() { - return Arrays.asList( - AnnotationNode.builder() - .setType(FIXED_TYPESTORE.get("Generated")) - .setDescription("by gapic-generator-java") - .build()); + return new TypeStore(concreteClazzes); } - private static Map createClassMemberVarExprs( + @Override + protected Map createClassMemberVarExprs( Service service, GapicContext context, TypeStore typeStore) { BiFunction varExprFn = (name, type) -> @@ -181,54 +123,25 @@ private static Map createClassMemberVarExprs( getMockServiceVarName(mixinService), typeStore.get(ClassNames.getMockServiceClassName(mixinService))); } - fields.put(SERVICE_HELPER_VAR_NAME, FIXED_TYPESTORE.get("MockServiceHelper")); + fields.put(SERVICE_HELPER_VAR_NAME, FIXED_GRPC_TYPESTORE.get("MockServiceHelper")); fields.put(CLIENT_VAR_NAME, typeStore.get(ClassNames.getServiceClientClassName(service))); - fields.put(CHANNEL_PROVIDER_VAR_NAME, FIXED_TYPESTORE.get("LocalChannelProvider")); - return fields.entrySet().stream() - .collect(Collectors.toMap(e -> e.getKey(), e -> varExprFn.apply(e.getKey(), e.getValue()))); - } - - private static List createClassMemberFieldDecls( - Map classMemberVarExprs) { - return classMemberVarExprs.values().stream() - .map( - v -> - ExprStatement.withExpr( - v.toBuilder() - .setIsDecl(true) - .setScope(ScopeNode.PRIVATE) - .setIsStatic(v.type().reference().name().startsWith("Mock")) - .build())) - .collect(Collectors.toList()); - } + fields.put(CHANNEL_PROVIDER_VAR_NAME, FIXED_GRPC_TYPESTORE.get("LocalChannelProvider")); - private static List createClassMethods( - Service service, - GapicContext context, - Map classMemberVarExprs, - TypeStore typeStore, - Map resourceNames) { - List javaMethods = new ArrayList<>(); - javaMethods.addAll(createTestAdminMethods(service, context, classMemberVarExprs, typeStore)); - javaMethods.addAll(createTestMethods(service, context, classMemberVarExprs, resourceNames)); - return javaMethods; + return fields.entrySet().stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + e -> varExprFn.apply(e.getKey(), e.getValue()), + (u, v) -> {throw new IllegalStateException();}, + LinkedHashMap::new)); } - private static List createTestAdminMethods( + @Override + protected MethodDefinition createStartStaticServerMethod( Service service, GapicContext context, Map classMemberVarExprs, TypeStore typeStore) { - List javaMethods = new ArrayList<>(); - javaMethods.add(createStartStaticServerMethod(service, context, classMemberVarExprs)); - javaMethods.add(createStopServerMethod(service, classMemberVarExprs)); - javaMethods.add(createSetUpMethod(service, classMemberVarExprs, typeStore)); - javaMethods.add(createTearDownMethod(service, classMemberVarExprs)); - return javaMethods; - } - - private static MethodDefinition createStartStaticServerMethod( - Service service, GapicContext context, Map classMemberVarExprs) { VariableExpr serviceHelperVarExpr = classMemberVarExprs.get(SERVICE_HELPER_VAR_NAME); Function serviceToVarExprFn = s -> classMemberVarExprs.get(getMockServiceVarName(s)); @@ -263,7 +176,7 @@ private static MethodDefinition createStartStaticServerMethod( MethodInvocationExpr secondArg = MethodInvocationExpr.builder() .setStaticReferenceType(FIXED_TYPESTORE.get("Arrays")) - .setGenerics(Arrays.asList(FIXED_TYPESTORE.get("MockGrpcService").reference())) + .setGenerics(Arrays.asList(FIXED_GRPC_TYPESTORE.get("MockGrpcService").reference())) .setMethodName("asList") .setArguments(mockServiceVarExprs) .build(); @@ -297,7 +210,8 @@ private static MethodDefinition createStartStaticServerMethod( .build(); } - private static MethodDefinition createStopServerMethod( + @Override + protected MethodDefinition createStopServerMethod( Service service, Map classMemberVarExprs) { return MethodDefinition.builder() .setAnnotations(Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("AfterClass")))) @@ -315,7 +229,8 @@ private static MethodDefinition createStopServerMethod( .build(); } - private static MethodDefinition createSetUpMethod( + @Override + protected MethodDefinition createSetUpMethod( Service service, Map classMemberVarExprs, TypeStore typeStore) { VariableExpr clientVarExpr = classMemberVarExprs.get(CLIENT_VAR_NAME); VariableExpr serviceHelperVarExpr = classMemberVarExprs.get(SERVICE_HELPER_VAR_NAME); @@ -413,7 +328,8 @@ private static MethodDefinition createSetUpMethod( .build(); } - private static MethodDefinition createTearDownMethod( + @Override + protected MethodDefinition createTearDownMethod( Service service, Map classMemberVarExprs) { return MethodDefinition.builder() .setAnnotations(Arrays.asList(AnnotationNode.withType(FIXED_TYPESTORE.get("After")))) @@ -432,406 +348,17 @@ private static MethodDefinition createTearDownMethod( .build(); } - private static List createTestMethods( - Service service, - GapicContext context, - Map classMemberVarExprs, - Map resourceNames) { - Map messageTypes = context.messages(); - List javaMethods = new ArrayList<>(); - for (Method method : service.methods()) { - Service matchingService = service; - if (method.isMixin()) { - int dotIndex = method.mixedInApiName().lastIndexOf("."); - String mixinServiceName = method.mixedInApiName().substring(dotIndex + 1); - String mixinServiceProtoPackage = method.mixedInApiName().substring(0, dotIndex); - Optional mixinServiceOpt = - context.mixinServices().stream() - .filter( - s -> - s.name().equals(mixinServiceName) - && s.protoPakkage().equals(mixinServiceProtoPackage)) - .findFirst(); - if (mixinServiceOpt.isPresent()) { - matchingService = mixinServiceOpt.get(); - } - } - - // Ignore variants for streaming methods as well. - if (method.methodSignatures().isEmpty() || !method.stream().equals(Method.Stream.NONE)) { - javaMethods.add( - createRpcTestMethod( - method, - service, - matchingService, - Collections.emptyList(), - 0, - true, - classMemberVarExprs, - resourceNames, - messageTypes)); - javaMethods.add( - createRpcExceptionTestMethod( - method, - matchingService, - Collections.emptyList(), - 0, - classMemberVarExprs, - resourceNames, - messageTypes)); - } else { - for (int i = 0; i < method.methodSignatures().size(); i++) { - javaMethods.add( - createRpcTestMethod( - method, - service, - matchingService, - method.methodSignatures().get(i), - i, - false, - classMemberVarExprs, - resourceNames, - messageTypes)); - javaMethods.add( - createRpcExceptionTestMethod( - method, - matchingService, - method.methodSignatures().get(i), - i, - classMemberVarExprs, - resourceNames, - messageTypes)); - } - } - } - return javaMethods; - } - - /** - * Creates a test method for a given RPC, e.g. createAssetTest. - * - * @param method the RPC for which this test method is created. - * @param apiService the host service under test. - * @param rpcService the service that {@code method} belongs to. This is not equal to {@code - * apiService} only when {@code method} is a mixin, in which case {@code rpcService} is the - * mixed-in service. If {@code apiService} and {@code rpcService} are different, they will be - * used only for pagination. Otherwise, {@code rpcService} subsumes {@code apiService}. - * @param methodSignature the method signature of the RPC under test. - * @param variantIndex the nth variant of the RPC under test. This applies when we have - * polymorphism due to the presence of several method signature annotations in the proto. - * @param isRequestArg whether the RPC variant under test take only the request proto message. - * @param classMemberVarExprs the class members in the generated test class. - * @param resourceNames the resource names available for use. - * @param messageTypes the proto message types available for use. - */ - private static MethodDefinition createRpcTestMethod( + @Override + protected List constructRpcTestCheckerLogic( Method method, - Service apiService, - Service rpcService, - List methodSignature, - int variantIndex, + Service service, boolean isRequestArg, Map classMemberVarExprs, - Map resourceNames, - Map messageTypes) { - if (!method.stream().equals(Method.Stream.NONE)) { - return createStreamingRpcTestMethod( - rpcService, method, classMemberVarExprs, resourceNames, messageTypes); - } - // Construct the expected response. - TypeNode methodOutputType = method.hasLro() ? method.lro().responseType() : method.outputType(); + VariableExpr requestVarExpr, + Message requestMessage, + List argExprs) { List methodExprs = new ArrayList<>(); - - TypeNode repeatedResponseType = null; - VariableExpr responsesElementVarExpr = null; - String mockServiceVarName = getMockServiceVarName(rpcService); - if (method.isPaged()) { - Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); - Field repeatedPagedResultsField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); - Preconditions.checkNotNull( - repeatedPagedResultsField, - String.format( - "No repeated field found for paged method %s with output message type %s", - method.name(), methodOutputMessage.name())); - - // Must be a non-repeated type. - repeatedResponseType = repeatedPagedResultsField.type(); - responsesElementVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(repeatedResponseType).setName("responsesElement").build()); - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(responsesElementVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - DefaultValueComposer.createDefaultValue( - Field.builder() - .setType(repeatedResponseType) - .setName("responsesElement") - .setIsMessage(!repeatedResponseType.isProtoPrimitiveType()) - .build())) - .build()); - } - - VariableExpr expectedResponseVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(methodOutputType).setName("expectedResponse").build()); - Expr expectedResponseValExpr = null; - if (method.isPaged()) { - Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); - Field firstRepeatedField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); - Preconditions.checkNotNull( - firstRepeatedField, - String.format( - "Expected paged RPC %s to have a repeated field in the response %s but found none", - method.name(), methodOutputMessage.name())); - - expectedResponseValExpr = - DefaultValueComposer.createSimplePagedResponse( - method.outputType(), firstRepeatedField.name(), responsesElementVarExpr); - } else { - if (messageTypes.containsKey(methodOutputType.reference().fullName())) { - expectedResponseValExpr = - DefaultValueComposer.createSimpleMessageBuilderExpr( - messageTypes.get(methodOutputType.reference().fullName()), - resourceNames, - messageTypes); - } else { - // Wrap this in a field so we don't have to split the helper into lots of different methods, - // or duplicate it for VariableExpr. - expectedResponseValExpr = - DefaultValueComposer.createDefaultValue( - Field.builder() - .setType(methodOutputType) - .setIsMessage(true) - .setName("expectedResponse") - .build()); - } - } - - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(expectedResponseVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(expectedResponseValExpr) - .build()); - - if (method.hasLro()) { - VariableExpr resultOperationVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setType(FIXED_TYPESTORE.get("Operation")) - .setName("resultOperation") - .build()); - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(resultOperationVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr( - DefaultValueComposer.createSimpleOperationBuilderExpr( - String.format("%sTest", JavaStyle.toLowerCamelCase(method.name())), - expectedResponseVarExpr)) - .build()); - methodExprs.add( - MethodInvocationExpr.builder() - .setExprReferenceExpr(classMemberVarExprs.get(mockServiceVarName)) - .setMethodName("addResponse") - .setArguments(resultOperationVarExpr) - .build()); - } else { - methodExprs.add( - MethodInvocationExpr.builder() - .setExprReferenceExpr(classMemberVarExprs.get(mockServiceVarName)) - .setMethodName("addResponse") - .setArguments(expectedResponseVarExpr) - .build()); - } List methodStatements = new ArrayList<>(); - methodStatements.addAll( - methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - methodExprs.clear(); - methodStatements.add(EMPTY_LINE_STATEMENT); - - // Construct the request or method arguments. - VariableExpr requestVarExpr = null; - Message requestMessage = null; - List argExprs = new ArrayList<>(); - if (isRequestArg) { - requestVarExpr = - VariableExpr.withVariable( - Variable.builder().setType(method.inputType()).setName("request").build()); - argExprs.add(requestVarExpr); - requestMessage = messageTypes.get(method.inputType().reference().fullName()); - Preconditions.checkNotNull(requestMessage); - Expr valExpr = - DefaultValueComposer.createSimpleMessageBuilderExpr( - requestMessage, resourceNames, messageTypes); - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(valExpr) - .build()); - } else { - for (MethodArgument methodArg : methodSignature) { - String methodArgName = JavaStyle.toLowerCamelCase(methodArg.name()); - VariableExpr varExpr = - VariableExpr.withVariable( - Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); - argExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(valExpr) - .build()); - } - } - methodStatements.addAll( - methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - methodExprs.clear(); - methodStatements.add(EMPTY_LINE_STATEMENT); - - // Call the RPC Java method. - VariableExpr actualResponseVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setType( - !method.isPaged() - ? methodOutputType - // If this method is a paginated mixin, use the host service, since - // ServiceClient defines the paged response class and the mixed-in service - // does not have a client. - : getPagedResponseType(method, method.isMixin() ? apiService : rpcService)) - .setName(method.isPaged() ? "pagedListResponse" : "actualResponse") - .build()); - Expr rpcJavaMethodInvocationExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(classMemberVarExprs.get("client")) - .setMethodName( - JavaStyle.toLowerCamelCase(method.name()) + (method.hasLro() ? "Async" : "")) - .setArguments(argExprs.stream().map(e -> (Expr) e).collect(Collectors.toList())) - .setReturnType(actualResponseVarExpr.type()) - .build(); - if (method.hasLro()) { - rpcJavaMethodInvocationExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(rpcJavaMethodInvocationExpr) - .setMethodName("get") - .setReturnType(rpcJavaMethodInvocationExpr.type()) - .build(); - } - - boolean returnsVoid = isProtoEmptyType(methodOutputType); - if (returnsVoid) { - methodExprs.add(rpcJavaMethodInvocationExpr); - } else { - methodExprs.add( - AssignmentExpr.builder() - .setVariableExpr(actualResponseVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(rpcJavaMethodInvocationExpr) - .build()); - } - - if (method.isPaged()) { - // Assign the resources variable. - VariableExpr resourcesVarExpr = - VariableExpr.withVariable( - Variable.builder() - .setType( - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(List.class) - .setGenerics(Arrays.asList(repeatedResponseType.reference())) - .build())) - .setName("resources") - .build()); - Expr iterateAllExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(actualResponseVarExpr) - .setMethodName("iterateAll") - .build(); - Expr resourcesValExpr = - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("Lists")) - .setMethodName("newArrayList") - .setArguments(iterateAllExpr) - .setReturnType(resourcesVarExpr.type()) - .build(); - - methodStatements.addAll( - methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - methodExprs.clear(); - methodStatements.add(EMPTY_LINE_STATEMENT); - - methodStatements.add( - ExprStatement.withExpr( - AssignmentExpr.builder() - .setVariableExpr(resourcesVarExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(resourcesValExpr) - .build())); - methodStatements.add(EMPTY_LINE_STATEMENT); - - // Assert the size is equivalent. - methodExprs.add( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) - .setMethodName("assertEquals") - .setArguments( - ValueExpr.withValue( - PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), - MethodInvocationExpr.builder() - .setExprReferenceExpr(resourcesVarExpr) - .setMethodName("size") - .setReturnType(TypeNode.INT) - .build()) - .build()); - - // Assert the responses are equivalent. - Message methodOutputMessage = messageTypes.get(method.outputType().reference().fullName()); - Field repeatedPagedResultsField = methodOutputMessage.findAndUnwrapFirstRepeatedField(); - Preconditions.checkNotNull( - repeatedPagedResultsField, - String.format( - "No repeated field found for paged method %s with output message type %s", - method.name(), methodOutputMessage.name())); - - Expr zeroExpr = - ValueExpr.withValue(PrimitiveValue.builder().setType(TypeNode.INT).setValue("0").build()); - Expr expectedPagedResponseExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(expectedResponseVarExpr) - .setMethodName( - String.format( - "get%sList", JavaStyle.toUpperCamelCase(repeatedPagedResultsField.name()))) - .build(); - expectedPagedResponseExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(expectedPagedResponseExpr) - .setMethodName("get") - .setArguments(zeroExpr) - .build(); - Expr actualPagedResponseExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(resourcesVarExpr) - .setMethodName("get") - .setArguments(zeroExpr) - .build(); - - methodExprs.add( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) - .setMethodName("assertEquals") - .setArguments(expectedPagedResponseExpr, actualPagedResponseExpr) - .build()); - } else if (!returnsVoid) { - methodExprs.add( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) - .setMethodName("assertEquals") - .setArguments(expectedResponseVarExpr, actualResponseVarExpr) - .build()); - } - methodStatements.addAll( - methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); - methodExprs.clear(); - methodStatements.add(EMPTY_LINE_STATEMENT); // Construct the request checker logic. VariableExpr actualRequestsVarExpr = @@ -851,7 +378,7 @@ private static MethodDefinition createRpcTestMethod( .setVariableExpr(actualRequestsVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr( MethodInvocationExpr.builder() - .setExprReferenceExpr(classMemberVarExprs.get(mockServiceVarName)) + .setExprReferenceExpr(classMemberVarExprs.get(getMockServiceVarName(service))) .setMethodName("getRequests") .setReturnType(actualRequestsVarExpr.type()) .build()) @@ -976,7 +503,7 @@ private static MethodDefinition createRpcTestMethod( .build(); Expr headerPatternExpr = MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("GaxGrpcProperties")) + .setStaticReferenceType(FIXED_GRPC_TYPESTORE.get("GaxGrpcProperties")) .setMethodName("getDefaultApiClientHeaderPattern") .build(); Expr headerSentExpr = @@ -995,22 +522,11 @@ private static MethodDefinition createRpcTestMethod( methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())); methodExprs.clear(); - String testMethodName = - String.format( - "%sTest%s", - JavaStyle.toLowerCamelCase(method.name()), variantIndex > 0 ? variantIndex + 1 : ""); - - return MethodDefinition.builder() - .setAnnotations(Arrays.asList(TEST_ANNOTATION)) - .setScope(ScopeNode.PUBLIC) - .setReturnType(TypeNode.VOID) - .setName(testMethodName) - .setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class))) - .setBody(methodStatements) - .build(); + return methodStatements; } - private static MethodDefinition createStreamingRpcTestMethod( + @Override + protected MethodDefinition createStreamingRpcTestMethod( Service service, Method method, Map classMemberVarExprs, @@ -1050,7 +566,7 @@ private static MethodDefinition createStreamingRpcTestMethod( VariableExpr resultOperationVarExpr = VariableExpr.withVariable( Variable.builder() - .setType(FIXED_TYPESTORE.get("Operation")) + .setType(FIXED_GRPC_TYPESTORE.get("Operation")) .setName("resultOperation") .build()); methodExprs.add( @@ -1103,7 +619,7 @@ private static MethodDefinition createStreamingRpcTestMethod( Variable.builder() .setType( TypeNode.withReference( - FIXED_TYPESTORE + FIXED_GRPC_TYPESTORE .get("MockStreamObserver") .reference() .copyAndSetGenerics(Arrays.asList(method.outputType().reference())))) @@ -1116,7 +632,7 @@ private static MethodDefinition createStreamingRpcTestMethod( .setVariableExpr(responseObserverVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr( NewObjectExpr.builder() - .setType(FIXED_TYPESTORE.get("MockStreamObserver")) + .setType(FIXED_GRPC_TYPESTORE.get("MockStreamObserver")) .setIsGeneric(true) .build()) .build())); @@ -1276,19 +792,8 @@ private static MethodDefinition createStreamingRpcTestMethod( .build(); } - /** - * Creates a test method to exercise exceptions for a given RPC, e.g. createAssetTest. - * - * @param method the RPC for which this test method is created. - * @param service the service that {@code method} belongs to. - * @param methodSignature the method signature of the RPC under test. - * @param variantIndex the nth variant of the RPC under test. This applies when we have - * polymorphism due to the presence of several method signature annotations in the proto. - * @param classMemberVarExprs the class members in the generated test class. - * @param resourceNames the resource names available for use. - * @param messageTypes the proto message types available for use. - */ - private static MethodDefinition createRpcExceptionTestMethod( + @Override + protected MethodDefinition createRpcExceptionTestMethod( Method method, Service service, List methodSignature, @@ -1299,7 +804,7 @@ private static MethodDefinition createRpcExceptionTestMethod( VariableExpr exceptionVarExpr = VariableExpr.withVariable( Variable.builder() - .setType(FIXED_TYPESTORE.get("StatusRuntimeException")) + .setType(FIXED_GRPC_TYPESTORE.get("StatusRuntimeException")) .setName("exception") .build()); @@ -1309,7 +814,7 @@ private static MethodDefinition createRpcExceptionTestMethod( .setVariableExpr(exceptionVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr( NewObjectExpr.builder() - .setType(FIXED_TYPESTORE.get("StatusRuntimeException")) + .setType(FIXED_GRPC_TYPESTORE.get("StatusRuntimeException")) .setArguments( EnumRefExpr.builder() .setType(GRPC_STATUS_TYPE) @@ -1354,7 +859,8 @@ private static MethodDefinition createRpcExceptionTestMethod( .build(); } - private static List createStreamingRpcExceptionTestStatements( + @Override + protected List createStreamingRpcExceptionTestStatements( Method method, Map classMemberVarExprs, Map resourceNames, @@ -1384,7 +890,7 @@ private static List createStreamingRpcExceptionTestStatements( Variable.builder() .setType( TypeNode.withReference( - FIXED_TYPESTORE + FIXED_GRPC_TYPESTORE .get("MockStreamObserver") .reference() .copyAndSetGenerics(Arrays.asList(method.outputType().reference())))) @@ -1397,7 +903,7 @@ private static List createStreamingRpcExceptionTestStatements( .setVariableExpr(responseObserverVarExpr.toBuilder().setIsDecl(true).build()) .setValueExpr( NewObjectExpr.builder() - .setType(FIXED_TYPESTORE.get("MockStreamObserver")) + .setType(FIXED_GRPC_TYPESTORE.get("MockStreamObserver")) .setIsGeneric(true) .build()) .build())); @@ -1538,104 +1044,8 @@ private static List createStreamingRpcExceptionTestStatements( return statements; } - private static List createRpcExceptionTestStatements( - Method method, - List methodSignature, - Map classMemberVarExprs, - Map resourceNames, - Map messageTypes) { - List argVarExprs = new ArrayList<>(); - List tryBodyExprs = new ArrayList<>(); - if (methodSignature.isEmpty()) { - // Construct the actual request. - VariableExpr varExpr = - VariableExpr.withVariable( - Variable.builder().setType(method.inputType()).setName("request").build()); - argVarExprs.add(varExpr); - Message requestMessage = messageTypes.get(method.inputType().reference().fullName()); - Preconditions.checkNotNull(requestMessage); - Expr valExpr = - DefaultValueComposer.createSimpleMessageBuilderExpr( - requestMessage, resourceNames, messageTypes); - tryBodyExprs.add( - AssignmentExpr.builder() - .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(valExpr) - .build()); - } else { - for (MethodArgument methodArg : methodSignature) { - String methodArgName = JavaStyle.toLowerCamelCase(methodArg.name()); - VariableExpr varExpr = - VariableExpr.withVariable( - Variable.builder().setType(methodArg.type()).setName(methodArgName).build()); - argVarExprs.add(varExpr); - Expr valExpr = DefaultValueComposer.createDefaultValue(methodArg, resourceNames); - tryBodyExprs.add( - AssignmentExpr.builder() - .setVariableExpr(varExpr.toBuilder().setIsDecl(true).build()) - .setValueExpr(valExpr) - .build()); - } - } - String rpcJavaName = JavaStyle.toLowerCamelCase(method.name()); - if (method.hasLro()) { - rpcJavaName += "Async"; - } - MethodInvocationExpr rpcJavaMethodInvocationExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(classMemberVarExprs.get("client")) - .setMethodName(rpcJavaName) - .setArguments(argVarExprs.stream().map(e -> (Expr) e).collect(Collectors.toList())) - .build(); - if (method.hasLro()) { - rpcJavaMethodInvocationExpr = - MethodInvocationExpr.builder() - .setExprReferenceExpr(rpcJavaMethodInvocationExpr) - .setMethodName("get") - .build(); - } - tryBodyExprs.add(rpcJavaMethodInvocationExpr); - - VariableExpr catchExceptionVarExpr = - VariableExpr.builder() - .setVariable( - Variable.builder() - .setType( - TypeNode.withExceptionClazz( - method.hasLro() - ? ExecutionException.class - : InvalidArgumentException.class)) - .setName("e") - .build()) - .build(); - - List catchBody = - method.hasLro() - ? createRpcLroExceptionTestCatchBody(catchExceptionVarExpr, false) - : Arrays.asList( - CommentStatement.withComment(LineComment.withComment("Expected exception."))); - // Assert a failure if no exception was raised. - tryBodyExprs.add( - MethodInvocationExpr.builder() - .setStaticReferenceType(FIXED_TYPESTORE.get("Assert")) - .setMethodName("fail") - .setArguments(ValueExpr.withValue(StringObjectValue.withValue("No exception raised"))) - .build()); - - TryCatchStatement tryCatchBlock = - TryCatchStatement.builder() - .setTryBody( - tryBodyExprs.stream() - .map(e -> ExprStatement.withExpr(e)) - .collect(Collectors.toList())) - .setCatchVariableExpr(catchExceptionVarExpr.toBuilder().setIsDecl(true).build()) - .setCatchBody(catchBody) - .build(); - - return Arrays.asList(EMPTY_LINE_STATEMENT, tryCatchBlock); - } - - private static List createRpcLroExceptionTestCatchBody( + @Override + protected List createRpcLroExceptionTestCatchBody( VariableExpr exceptionExpr, boolean isStreaming) { List catchBodyExprs = new ArrayList<>(); @@ -1726,244 +1136,4 @@ private static List createRpcLroExceptionTestCatchBody( return catchBodyExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()); } - - /* ========================================= - * Type creator methods. - * ========================================= - */ - - private static TypeStore createStaticTypes() { - List concreteClazzes = - Arrays.asList( - AbstractMessage.class, - After.class, - AfterClass.class, - Any.class, - ApiClientHeaderProvider.class, - ApiStreamObserver.class, - Arrays.class, - Assert.class, - Before.class, - BeforeClass.class, - BidiStreamingCallable.class, - ClientStreamingCallable.class, - ExecutionException.class, - GaxGrpcProperties.class, - Generated.class, - IOException.class, - InvalidArgumentException.class, - List.class, - Lists.class, - NoCredentialsProvider.class, - Operation.class, - ServerStreamingCallable.class, - StatusCode.class, - StatusRuntimeException.class, - Test.class, - UUID.class); - TypeStore typeStore = new TypeStore(concreteClazzes); - typeStore.putAll( - GRPC_TESTING_PACKAGE, - Arrays.asList( - "LocalChannelProvider", "MockGrpcService", "MockServiceHelper", "MockStreamObserver")); - return typeStore; - } - - private static Map createDefaultMethodNamesToTypes() { - Function typeMakerFn = - c -> TypeNode.withReference(ConcreteReference.withClazz(c)); - Map javaMethodNameToReturnType = new LinkedHashMap<>(); - javaMethodNameToReturnType.put( - "defaultExecutorProviderBuilder", - typeMakerFn.apply(InstantiatingExecutorProvider.Builder.class)); - javaMethodNameToReturnType.put("getDefaultEndpoint", TypeNode.STRING); - javaMethodNameToReturnType.put( - "getDefaultServiceScopes", - TypeNode.withReference( - ConcreteReference.builder() - .setClazz(List.class) - .setGenerics(Arrays.asList(TypeNode.STRING.reference())) - .build())); - javaMethodNameToReturnType.put( - "defaultCredentialsProviderBuilder", - typeMakerFn.apply(GoogleCredentialsProvider.Builder.class)); - javaMethodNameToReturnType.put( - "defaultGrpcTransportProviderBuilder", - typeMakerFn.apply(InstantiatingGrpcChannelProvider.Builder.class)); - javaMethodNameToReturnType.put( - "defaultTransportChannelProvider", FIXED_TYPESTORE.get("TransportChannelProvider")); - return javaMethodNameToReturnType; - } - - private static void addDynamicTypes(GapicContext context, Service service, TypeStore typeStore) { - typeStore.putAll( - service.pakkage(), - Arrays.asList( - ClassNames.getMockServiceClassName(service), - ClassNames.getServiceClientClassName(service), - ClassNames.getServiceSettingsClassName(service))); - // Pagination types. - typeStore.putAll( - service.pakkage(), - service.methods().stream() - .filter(m -> m.isPaged()) - .map(m -> String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, m.name())) - .collect(Collectors.toList()), - true, - ClassNames.getServiceClientClassName(service)); - for (Service mixinService : context.mixinServices()) { - typeStore.put(mixinService.pakkage(), ClassNames.getMockServiceClassName(mixinService)); - for (Method mixinMethod : mixinService.methods()) { - if (!mixinMethod.isPaged()) { - continue; - } - typeStore.put( - service.pakkage(), - String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, mixinMethod.name()), - true, - ClassNames.getServiceClientClassName(service)); - } - } - } - - private static TypeNode getOperationCallSettingsType(Method protoMethod) { - return getOperationCallSettingsTypeHelper(protoMethod, false); - } - - private static TypeNode getOperationCallSettingsBuilderType(Method protoMethod) { - return getOperationCallSettingsTypeHelper(protoMethod, true); - } - - private static TypeNode getOperationCallSettingsTypeHelper( - Method protoMethod, boolean isBuilder) { - Preconditions.checkState( - protoMethod.hasLro(), - String.format("Cannot get OperationCallSettings on non-LRO method %s", protoMethod.name())); - Class callSettingsClazz = - isBuilder ? OperationCallSettings.Builder.class : OperationCallSettings.class; - return TypeNode.withReference( - ConcreteReference.builder() - .setClazz(callSettingsClazz) - .setGenerics( - Arrays.asList( - protoMethod.inputType().reference(), - protoMethod.lro().responseType().reference(), - protoMethod.lro().metadataType().reference())) - .build()); - } - - private static TypeNode getCallSettingsType(Method protoMethod, TypeStore typeStore) { - return getCallSettingsTypeHelper(protoMethod, typeStore, false); - } - - private static TypeNode getCallSettingsBuilderType(Method protoMethod, TypeStore typeStore) { - return getCallSettingsTypeHelper(protoMethod, typeStore, true); - } - - private static TypeNode getCallSettingsTypeHelper( - Method protoMethod, TypeStore typeStore, boolean isBuilder) { - Class callSettingsClazz = isBuilder ? UnaryCallSettings.Builder.class : UnaryCallSettings.class; - if (protoMethod.isPaged()) { - callSettingsClazz = isBuilder ? PagedCallSettings.Builder.class : PagedCallSettings.class; - } else { - switch (protoMethod.stream()) { - case CLIENT: - // Fall through. - case BIDI: - callSettingsClazz = - isBuilder ? StreamingCallSettings.Builder.class : StreamingCallSettings.class; - break; - case SERVER: - callSettingsClazz = - isBuilder - ? ServerStreamingCallSettings.Builder.class - : ServerStreamingCallSettings.class; - break; - case NONE: - // Fall through - default: - // Fall through - } - } - - List generics = new ArrayList<>(); - generics.add(protoMethod.inputType().reference()); - generics.add(protoMethod.outputType().reference()); - if (protoMethod.isPaged()) { - generics.add( - typeStore - .get(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, protoMethod.name())) - .reference()); - } - - return TypeNode.withReference( - ConcreteReference.builder().setClazz(callSettingsClazz).setGenerics(generics).build()); - } - - private static TypeNode getCallableType(Method protoMethod) { - Preconditions.checkState( - !protoMethod.stream().equals(Method.Stream.NONE), - "No callable type exists for non-streaming methods."); - - Class callableClazz = ClientStreamingCallable.class; - switch (protoMethod.stream()) { - case BIDI: - callableClazz = BidiStreamingCallable.class; - break; - case SERVER: - callableClazz = ServerStreamingCallable.class; - break; - case CLIENT: - // Fall through. - case NONE: - // Fall through - default: - // Fall through - } - - List generics = new ArrayList<>(); - generics.add(protoMethod.inputType().reference()); - generics.add(protoMethod.outputType().reference()); - - return TypeNode.withReference( - ConcreteReference.builder().setClazz(callableClazz).setGenerics(generics).build()); - } - - private static TypeNode getPagedResponseType(Method method, Service service) { - return TypeNode.withReference( - VaporReference.builder() - .setName(String.format(PAGED_RESPONSE_TYPE_NAME_PATTERN, method.name())) - .setPakkage(service.pakkage()) - .setEnclosingClassNames(ClassNames.getServiceClientClassName(service)) - .setIsStaticImport(true) - .build()); - } - - private static String getCallableMethodName(Method protoMethod) { - Preconditions.checkState( - !protoMethod.stream().equals(Method.Stream.NONE), - "No callable type exists for non-streaming methods."); - - switch (protoMethod.stream()) { - case BIDI: - return "bidiStreamingCall"; - case SERVER: - return "serverStreamingCall"; - case CLIENT: - // Fall through. - case NONE: - // Fall through - default: - return "clientStreamingCall"; - } - } - - private static String getMockServiceVarName(Service service) { - return String.format(MOCK_SERVICE_VAR_NAME_PATTERN, service.name()); - } - - private static boolean isProtoEmptyType(TypeNode type) { - return type.reference().pakkage().equals("com.google.protobuf") - && type.reference().name().equals("Empty"); - } } diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceSettingsClassComposer.java index 6ac112f2ec..9d4c9bc294 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceSettingsClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceSettingsClassComposer.java @@ -20,6 +20,10 @@ public class ServiceSettingsClassComposer extends AbstractServiceSettingsClassCo private static final ServiceSettingsClassComposer INSTANCE = new ServiceSettingsClassComposer(); + protected ServiceSettingsClassComposer() { + super(GrpcContext.instance()); + } + public static ServiceSettingsClassComposer instance() { return INSTANCE; } diff --git a/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java new file mode 100644 index 0000000000..9d96aba607 --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposer.java @@ -0,0 +1,182 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.composer.grpc; + +import com.google.api.gax.grpc.GaxGrpcProperties; +import com.google.api.gax.grpc.GrpcTransportChannel; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.generator.engine.ast.AnnotationNode; +import com.google.api.generator.engine.ast.ConcreteReference; +import com.google.api.generator.engine.ast.MethodDefinition; +import com.google.api.generator.engine.ast.MethodInvocationExpr; +import com.google.api.generator.engine.ast.ScopeNode; +import com.google.api.generator.engine.ast.StringObjectValue; +import com.google.api.generator.engine.ast.TypeNode; +import com.google.api.generator.engine.ast.ValueExpr; +import com.google.api.generator.engine.ast.Variable; +import com.google.api.generator.engine.ast.VariableExpr; +import com.google.api.generator.gapic.composer.common.AbstractServiceStubSettingsClassComposer; +import com.google.api.generator.gapic.composer.comment.SettingsCommentComposer; +import com.google.api.generator.gapic.composer.store.TypeStore; +import com.google.api.generator.gapic.composer.utils.ClassNames; +import com.google.api.generator.gapic.model.Service; +import java.util.Arrays; +import java.util.List; + +public class ServiceStubSettingsClassComposer extends AbstractServiceStubSettingsClassComposer { + private static final ServiceStubSettingsClassComposer INSTANCE = + new ServiceStubSettingsClassComposer(); + + protected static final TypeStore FIXED_GRPC_TYPESTORE = createStaticTypes(); + + public static ServiceStubSettingsClassComposer instance() { + return INSTANCE; + } + + protected ServiceStubSettingsClassComposer() { + super(GrpcContext.instance()); + } + + private static TypeStore createStaticTypes() { + List concreteClazzes = + Arrays.asList( + GaxGrpcProperties.class, + GrpcTransportChannel.class, + InstantiatingGrpcChannelProvider.class); + return new TypeStore(concreteClazzes); + } + + @Override + protected MethodDefinition createDefaultTransportTransportProviderBuilderMethod() { + // Create the defaultGrpcTransportProviderBuilder method. + TypeNode returnType = + TypeNode.withReference( + ConcreteReference.withClazz(InstantiatingGrpcChannelProvider.Builder.class)); + MethodInvocationExpr transportChannelProviderBuilderExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_GRPC_TYPESTORE.get(InstantiatingGrpcChannelProvider.class.getSimpleName())) + .setMethodName("newBuilder") + .build(); + transportChannelProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(transportChannelProviderBuilderExpr) + .setMethodName("setMaxInboundMessageSize") + .setArguments( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build()) + .setStaticReferenceType(TypeNode.INT_OBJECT) + .build()) + .setReturnType(returnType) + .build(); + return MethodDefinition.builder() + .setHeaderCommentStatements( + SettingsCommentComposer.DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultGrpcTransportProviderBuilder") + .setReturnExpr(transportChannelProviderBuilderExpr) + .build(); + } + + @Override + protected MethodDefinition createDefaultApiClientHeaderProviderBuilderMethod( + Service service, TypeStore typeStore) { + // Create the defaultApiClientHeaderProviderBuilder method. + TypeNode returnType = + TypeNode.withReference(ConcreteReference.withClazz(ApiClientHeaderProvider.Builder.class)); + MethodInvocationExpr returnExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("ApiClientHeaderProvider")) + .setMethodName("newBuilder") + .build(); + + MethodInvocationExpr versionArgExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(FIXED_TYPESTORE.get("GaxProperties")) + .setMethodName("getLibraryVersion") + .setArguments( + VariableExpr.builder() + .setVariable( + Variable.builder().setType(TypeNode.CLASS_OBJECT).setName("class").build()) + .setStaticReferenceType( + typeStore.get(ClassNames.getServiceStubSettingsClassName(service))) + .build()) + .build(); + + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setGeneratedLibToken") + .setArguments(ValueExpr.withValue(StringObjectValue.withValue("gapic")), versionArgExpr) + .build(); + returnExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(returnExpr) + .setMethodName("setTransportToken") + .setArguments( + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) + .setMethodName("getGrpcTokenName") + .build(), + MethodInvocationExpr.builder() + .setStaticReferenceType( + FIXED_GRPC_TYPESTORE.get(GaxGrpcProperties.class.getSimpleName())) + .setMethodName("getGrpcVersion") + .build()) + .setReturnType(returnType) + .build(); + + AnnotationNode annotation = + AnnotationNode.builder() + .setType(FIXED_TYPESTORE.get("BetaApi")) + .setDescription( + "The surface for customizing headers is not stable yet and may change in the" + + " future.") + .build(); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(annotation)) + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultApiClientHeaderProviderBuilder") + .setReturnExpr(returnExpr) + .build(); + } + + @Override + public MethodDefinition createDefaultTransportChannelProviderMethod() { + TypeNode returnType = FIXED_TYPESTORE.get("TransportChannelProvider"); + MethodInvocationExpr transportProviderBuilderExpr = + MethodInvocationExpr.builder().setMethodName("defaultGrpcTransportProviderBuilder").build(); + transportProviderBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(transportProviderBuilderExpr) + .setMethodName("build") + .setReturnType(returnType) + .build(); + return MethodDefinition.builder() + .setScope(ScopeNode.PUBLIC) + .setIsStatic(true) + .setReturnType(returnType) + .setName("defaultTransportChannelProvider") + .setReturnExpr(transportProviderBuilderExpr) + .build(); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java index 50e8a8ce4a..f1abb45a4c 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java +++ b/src/main/java/com/google/api/generator/gapic/composer/utils/ClassNames.java @@ -26,12 +26,6 @@ public class ClassNames { private static final String SERVICE_SETTINGS_CLASS_NAME_PATTERN = "%sSettings"; private static final String SERVICE_STUB_SETTINGS_CLASS_NAME_PATTERN = "%sStubSettings"; private static final String SERVICE_STUB_CLASS_NAME_PATTERN = "%sStub"; - - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - private static final String GRPC_SERVICE_STUB_CLASS_NAME_PATTERN = "Grpc%sStub"; - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - private static final String GRPC_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN = - "Grpc%sCallableFactory"; private static final String TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN = "%s%sStub"; private static final String TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN = "%s%sCallableFactory"; @@ -64,13 +58,6 @@ public static String getServiceStubClassName(Service service) { SERVICE_STUB_CLASS_NAME_PATTERN, monolithBackwardsCompatibleName(service.name())); } - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - public static String getGrpcServiceCallableFactoryClassName(Service service) { - return String.format( - GRPC_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, - monolithBackwardsCompatibleName(service.name())); - } - public String getTransportServiceCallableFactoryClassName(Service service) { return String.format( TRANSPORT_SERVICE_CALLABLE_FACTORY_CLASS_NAME_PATTERN, @@ -78,12 +65,6 @@ public String getTransportServiceCallableFactoryClassName(Service service) { monolithBackwardsCompatibleName(service.name())); } - // TODO: remove after Pre-DIREGAPIC refactoring is fully merged - public static String getGrpcServiceStubClassName(Service service) { - return String.format( - GRPC_SERVICE_STUB_CLASS_NAME_PATTERN, monolithBackwardsCompatibleName(service.name())); - } - public String getTransportServiceStubClassName(Service service) { return String.format( TRANSPORT_SERVICE_STUB_CLASS_NAME_PATTERN, diff --git a/src/main/java/com/google/api/generator/gapic/model/GapicContext.java b/src/main/java/com/google/api/generator/gapic/model/GapicContext.java index 0cc3186e51..8767d06a8f 100644 --- a/src/main/java/com/google/api/generator/gapic/model/GapicContext.java +++ b/src/main/java/com/google/api/generator/gapic/model/GapicContext.java @@ -75,7 +75,7 @@ static GapicMetadata defaultGapicMetadata() { public abstract Builder toBuilder(); - public abstract TransportContext transportContext(); + public abstract Transport transport(); public static Builder builder() { return new AutoValue_GapicContext.Builder() @@ -108,7 +108,7 @@ public Builder setHelperResourceNames(Set helperResourceNames) { public abstract Builder setGapicMetadataEnabled(boolean gapicMetadataEnabled); - public abstract Builder setTransportContext(TransportContext transportContext); + public abstract Builder setTransport(Transport transport); public abstract GapicContext build(); } diff --git a/src/main/java/com/google/api/generator/gapic/model/Transport.java b/src/main/java/com/google/api/generator/gapic/model/Transport.java new file mode 100644 index 0000000000..aeb7b9361c --- /dev/null +++ b/src/main/java/com/google/api/generator/gapic/model/Transport.java @@ -0,0 +1,33 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.gapic.model; + +public enum Transport { + REST, + GRPC, + // Never used in the context as is, must be split into two contexts (REST and GRPC respectively) + // instead. + GRPC_REST; + + /** + * Parse command line transport argument in the format `grpc+rest`. + * + * @param name name of the transport. Valid inputs are "grpc", "rest", "grpc+rest" + * @return the {@code Transport} enum matching the command line argument + */ + public static Transport parse(String name) { + return valueOf(name.replace('+', '_').toUpperCase()); + } +} diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java index 51e84cb57b..cd2ae640c9 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/HttpRuleParser.java @@ -50,15 +50,24 @@ public static Optional> parseHttpBindings( checkHttpFieldIsValid(httpRule.getBody(), inputMessage, true); } + return parseHttpRuleHelper(httpRule, Optional.of(inputMessage), messageTypes); + } + + public static Optional> parseHttpRule(HttpRule httpRule) { + return parseHttpRuleHelper(httpRule, Optional.empty(), Collections.emptyMap()); + } + + private static Optional> parseHttpRuleHelper( + HttpRule httpRule, Optional inputMessageOpt, Map messageTypes) { // Get pattern. - Set uniqueBindings = getPatternBindings(httpRule); + Set uniqueBindings = getHttpVerbPattern(httpRule); if (uniqueBindings.isEmpty()) { return Optional.empty(); } if (httpRule.getAdditionalBindingsCount() > 0) { for (HttpRule additionalRule : httpRule.getAdditionalBindingsList()) { - uniqueBindings.addAll(getPatternBindings(additionalRule)); + uniqueBindings.addAll(getHttpVerbPattern(additionalRule)); } } @@ -69,19 +78,23 @@ public static Optional> parseHttpBindings( for (String binding : bindings) { // Handle foo.bar cases by descending into the subfields. String[] descendantBindings = binding.split("\\."); - Message containingMessage = inputMessage; + Optional containingMessageOpt = inputMessageOpt; for (int i = 0; i < descendantBindings.length; i++) { String subField = descendantBindings[i]; + if (!containingMessageOpt.isPresent()) { + continue; + } + if (i < descendantBindings.length - 1) { - Field field = containingMessage.fieldMap().get(subField); - containingMessage = messageTypes.get(field.type().reference().fullName()); + Field field = containingMessageOpt.get().fieldMap().get(subField); + containingMessageOpt = Optional.of(messageTypes.get(field.type().reference().fullName())); Preconditions.checkNotNull( - containingMessage, + containingMessageOpt.get(), String.format( "No containing message found for field %s with type %s", field.name(), field.type().reference().simpleName())); } else { - checkHttpFieldIsValid(subField, containingMessage, false); + checkHttpFieldIsValid(subField, containingMessageOpt.get(), false); } } } @@ -89,7 +102,7 @@ public static Optional> parseHttpBindings( return Optional.of(bindings); } - private static Set getPatternBindings(HttpRule httpRule) { + private static Set getHttpVerbPattern(HttpRule httpRule) { String pattern = null; // Assign a temp variable to prevent the formatter from removing the import. PatternCase patternCase = httpRule.getPatternCase(); diff --git a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java index 37f4627b52..a088e8ae46 100644 --- a/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java +++ b/src/main/java/com/google/api/generator/gapic/protoparser/Parser.java @@ -15,10 +15,11 @@ package com.google.api.generator.gapic.protoparser; import com.google.api.ClientProto; +import com.google.api.DocumentationRule; +import com.google.api.HttpRule; import com.google.api.ResourceDescriptor; import com.google.api.ResourceProto; import com.google.api.generator.engine.ast.TypeNode; -import com.google.api.generator.gapic.composer.grpc.GrpcContext; import com.google.api.generator.gapic.model.Field; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicContext; @@ -32,6 +33,7 @@ import com.google.api.generator.gapic.model.ResourceReference; import com.google.api.generator.gapic.model.Service; import com.google.api.generator.gapic.model.SourceCodeInfoLocation; +import com.google.api.generator.gapic.model.Transport; import com.google.api.generator.gapic.utils.ResourceNameConstants; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; @@ -184,7 +186,7 @@ public static GapicContext parse(CodeGeneratorRequest request) { .setServiceConfig(serviceConfigOpt.isPresent() ? serviceConfigOpt.get() : null) .setGapicMetadataEnabled(willGenerateMetadata) .setServiceYamlProto(serviceYamlProtoOpt.isPresent() ? serviceYamlProtoOpt.get() : null) - .setTransportContext(GrpcContext.instance()) + .setTransport(Transport.GRPC) .build(); } @@ -241,6 +243,33 @@ public static List parseServices( .filter(a -> MIXIN_ALLOWLIST.contains(a.getName())) .map(a -> a.getName()) .collect(Collectors.toSet()); + // Holds the methods to be mixed in. + // Key: proto_package.ServiceName.RpcName. + // Value: HTTP rules, which clobber those in the proto. + // Assumes that http.rules.selector always specifies RPC names in the above format. + Map> mixedInMethodsToHttpRules = new HashMap<>(); + Map mixedInMethodsToDocs = new HashMap<>(); + // Parse HTTP rules and documentation, which will override the proto. + if (serviceYamlProtoOpt.isPresent()) { + for (HttpRule httpRule : serviceYamlProtoOpt.get().getHttp().getRulesList()) { + Optional> httpBindingsOpt = HttpRuleParser.parseHttpRule(httpRule); + if (!httpBindingsOpt.isPresent()) { + continue; + } + for (String rpcFullNameRaw : httpRule.getSelector().split(",")) { + String rpcFullName = rpcFullNameRaw.trim(); + mixedInMethodsToHttpRules.put(rpcFullName, httpBindingsOpt.get()); + } + } + for (DocumentationRule docRule : + serviceYamlProtoOpt.get().getDocumentation().getRulesList()) { + for (String rpcFullNameRaw : docRule.getSelector().split(",")) { + String rpcFullName = rpcFullNameRaw.trim(); + mixedInMethodsToDocs.put(rpcFullName, docRule.getDescription()); + } + } + } + Set apiDefinedRpcs = new HashSet<>(); for (Service service : services) { if (blockedCodegenMixinApis.contains(service)) { @@ -254,28 +283,55 @@ public static List parseServices( if (servicesContainBlocklistedApi && !mixedInApis.isEmpty()) { for (int i = 0; i < services.size(); i++) { Service originalService = services.get(i); - List updatedMethods = new ArrayList<>(originalService.methods()); + List updatedOriginalServiceMethods = new ArrayList<>(originalService.methods()); // If mixin APIs are present, add the methods to all other services. for (Service mixinService : blockedCodegenMixinApis) { - if (!mixedInApis.contains( - String.format("%s.%s", mixinService.protoPakkage(), mixinService.name()))) { + final String mixinServiceFullName = serviceFullNameFn.apply(mixinService); + if (!mixedInApis.contains(mixinServiceFullName)) { continue; } - mixinService - .methods() + Function methodToFullProtoNameFn = + m -> String.format("%s.%s", mixinServiceFullName, m.name()); + // Filter mixed-in methods based on those listed in the HTTP rules section of + // service.yaml. + List updatedMixinMethods = + mixinService.methods().stream() + // Mixin method inclusion is based on the HTTP rules list in service.yaml. + .filter( + m -> mixedInMethodsToHttpRules.containsKey(methodToFullProtoNameFn.apply(m))) + .map( + m -> { + // HTTP rules and RPC documentation in the service.yaml file take + // precedence. + String fullMethodName = methodToFullProtoNameFn.apply(m); + List httpBindings = + mixedInMethodsToHttpRules.containsKey(fullMethodName) + ? mixedInMethodsToHttpRules.get(fullMethodName) + : m.httpBindings(); + String docs = + mixedInMethodsToDocs.containsKey(fullMethodName) + ? mixedInMethodsToDocs.get(fullMethodName) + : m.description(); + return m.toBuilder() + .setHttpBindings(httpBindings) + .setDescription(docs) + .build(); + }) + .collect(Collectors.toList()); + // Overridden RPCs defined in the protos take precedence. + updatedMixinMethods.stream() + .filter(m -> !apiDefinedRpcs.contains(m.name())) .forEach( - m -> { - // Overridden RPCs defined in the protos take precedence. - if (!apiDefinedRpcs.contains(m.name())) { - updatedMethods.add( + m -> + updatedOriginalServiceMethods.add( m.toBuilder() .setMixedInApiName(serviceFullNameFn.apply(mixinService)) - .build()); - } - }); - outputMixinServiceSet.add(mixinService); + .build())); + outputMixinServiceSet.add( + mixinService.toBuilder().setMethods(updatedMixinMethods).build()); } - services.set(i, originalService.toBuilder().setMethods(updatedMethods).build()); + services.set( + i, originalService.toBuilder().setMethods(updatedOriginalServiceMethods).build()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel index 73ea3d0a82..1ad263ea22 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/BUILD.bazel @@ -4,25 +4,10 @@ load("//:rules_bazel/java/java_diff_test.bzl", "golden_update") package(default_visibility = ["//visibility:public"]) UPDATE_GOLDENS_TESTS = [ - "BatchingDescriptorComposerTest", "ComposerTest", - "GrpcServiceCallableFactoryClassComposerTest", - "GrpcServiceStubClassComposerTest", - "MockServiceClassComposerTest", - "MockServiceImplClassComposerTest", - "ServiceClientClassComposerTest", - "ServiceClientTestClassComposerTest", - "ServiceStubSettingsClassComposerTest", - "ServiceStubClassComposerTest", ] -COMMON_SRCS = [ - "TestProtoLoaderUtil.java", -] - -TESTS = UPDATE_GOLDENS_TESTS + [ - "RetrySettingsComposerTest", -] +TESTS = UPDATE_GOLDENS_TESTS TEST_DEPS = [ ":common_resources_java_proto", @@ -41,8 +26,6 @@ TEST_DEPS = [ "//src/test/java/com/google/api/generator/gapic/testdata:deprecated_service_java_proto", "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", "//src/test/java/com/google/api/generator/gapic/testdata:testgapic_java_proto", - "//src/test/java/com/google/api/generator/gapic/composer/common", - "//src/test/java/com/google/api/generator/gapic/composer/constants", "@com_google_api_api_common//jar", "@com_google_api_gax_java//gax", "@com_google_api_api_common", @@ -78,7 +61,7 @@ java_proto_library( name = test_name, srcs = [ "{0}.java".format(test_name), - ] + COMMON_SRCS, + ], data = [ "//src/test/java/com/google/api/generator/gapic/composer/goldens:goldens_files", "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", @@ -88,7 +71,6 @@ java_proto_library( deps = TEST_DEPS, ) for test_name in TESTS] -TEST_CLASS_DIR = "com.google.api.generator.gapic.composer." # Run `bazel run src/test/java/com/google/api/generator/gapic/composer:testTargetName_update` # to update goldens as expected generated code. # `ServiceClient*` tests are not supported now since they are still in active development. @@ -97,7 +79,7 @@ TEST_CLASS_DIR = "com.google.api.generator.gapic.composer." name = "{0}_update".format(test_name), srcs = [ "{0}.java".format(test_name), - ] + COMMON_SRCS, + ], data = [ "//src/test/java/com/google/api/generator/gapic/composer/goldens:goldens_files", "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", diff --git a/src/test/java/com/google/api/generator/gapic/composer/ComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ComposerTest.java index d033c94f49..d4ceeabce2 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ComposerTest.java @@ -17,7 +17,6 @@ import com.google.api.generator.engine.ast.ClassDefinition; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicClass.Kind; import com.google.api.generator.test.framework.Assert; @@ -43,7 +42,7 @@ public void gapicClass_addApacheLicense() { gapicClassWithHeaderList.get(0).classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "ComposerPostProcOnFooBar.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "ComposerPostProcOnFooBar.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "ComposerPostProcOnFooBar.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/TestProtoLoaderUtil.java b/src/test/java/com/google/api/generator/gapic/composer/TestProtoLoaderUtil.java deleted file mode 100644 index 03beb05955..0000000000 --- a/src/test/java/com/google/api/generator/gapic/composer/TestProtoLoaderUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2021 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.api.generator.gapic.composer; - -import com.google.api.generator.gapic.composer.common.TestProtoLoader; -import com.google.api.generator.gapic.model.GapicContext; - -// TODO: remove after Pre-DIREGAPIC refactoring is fully merged -public class TestProtoLoaderUtil { - public static GapicContext parseDeprecatedService() { - return TestProtoLoader.instance().parseDeprecatedService(); - } - - public static GapicContext parseShowcaseEcho() { - return TestProtoLoader.instance().parseShowcaseEcho(); - } - - public static GapicContext parseShowcaseIdentity() { - return TestProtoLoader.instance().parseShowcaseIdentity(); - } - - public static GapicContext parseShowcaseTesting() { - return TestProtoLoader.instance().parseShowcaseTesting(); - } - - public static GapicContext parsePubSubPublisher() { - return TestProtoLoader.instance().parsePubSubPublisher(); - } - - public static GapicContext parseLogging() { - return TestProtoLoader.instance().parseLogging(); - } -} diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel index e8d4fce1e9..1d8c68ad72 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/common/BUILD.bazel @@ -4,9 +4,13 @@ load("//:rules_bazel/java/java_diff_test.bzl", "golden_update") package(default_visibility = ["//visibility:public"]) UPDATE_GOLDENS_TESTS = [ + "BatchingDescriptorComposerTest", + "ServiceClientClassComposerTest", + "ServiceStubClassComposerTest", ] TESTS = UPDATE_GOLDENS_TESTS + [ + "RetrySettingsComposerTest", ] TEST_DEPS = [ @@ -70,6 +74,7 @@ java_proto_library( "{0}.java".format(test_name), ], data = [ + "//src/test/java/com/google/api/generator/gapic/composer/common/goldens:goldens_files", "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", ], @@ -87,6 +92,7 @@ java_proto_library( "{0}.java".format(test_name), ], data = [ + "//src/test/java/com/google/api/generator/gapic/composer/common/goldens:goldens_files", "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", ], diff --git a/src/test/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposerTest.java similarity index 92% rename from src/test/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposerTest.java index 1d674d9fdb..f2ac7a5da5 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/BatchingDescriptorComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/BatchingDescriptorComposerTest.java @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import com.google.api.generator.engine.ast.Expr; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicServiceConfig; import com.google.api.generator.gapic.model.Message; @@ -82,13 +81,13 @@ public void batchingDescriptor_hasSubresponseField() { outputResourceNames); String filename = "pubsub_gapic.yaml"; - Path path = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, filename); + Path path = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), filename); Optional> batchingSettingsOpt = BatchingSettingsConfigParser.parse(Optional.of(path.toString())); assertTrue(batchingSettingsOpt.isPresent()); String jsonFilename = "pubsub_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional configOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(configOpt.isPresent()); GapicServiceConfig config = configOpt.get(); @@ -109,7 +108,7 @@ public void batchingDescriptor_hasSubresponseField() { this.getClass(), "BatchingDescriptorComposerTestSubresponse.golden", writerVisitor.write()); Path goldenFilePath = Paths.get( - ComposerConstants.GOLDENFILES_DIRECTORY, + Utils.getGoldenDir(this.getClass()), "BatchingDescriptorComposerTestSubresponse.golden"); Assert.assertCodeEquals(goldenFilePath, writerVisitor.write()); } @@ -144,13 +143,13 @@ public void batchingDescriptor_noSubresponseField() { outputResourceNames); String filename = "logging_gapic.yaml"; - Path path = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, filename); + Path path = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), filename); Optional> batchingSettingsOpt = BatchingSettingsConfigParser.parse(Optional.of(path.toString())); assertTrue(batchingSettingsOpt.isPresent()); String jsonFilename = "logging_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional configOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(configOpt.isPresent()); GapicServiceConfig config = configOpt.get(); @@ -173,7 +172,7 @@ public void batchingDescriptor_noSubresponseField() { writerVisitor.write()); Path goldenFilePath = Paths.get( - ComposerConstants.GOLDENFILES_DIRECTORY, + Utils.getGoldenDir(this.getClass()), "BatchingDescriptorComposerTestNoSubresponse.golden"); Assert.assertCodeEquals(goldenFilePath, writerVisitor.write()); } diff --git a/src/test/java/com/google/api/generator/gapic/composer/RetrySettingsComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java similarity index 94% rename from src/test/java/com/google/api/generator/gapic/composer/RetrySettingsComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java index 1344230b8a..09b1bf5b1c 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/RetrySettingsComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposerTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; @@ -27,7 +27,6 @@ import com.google.api.generator.engine.ast.Variable; import com.google.api.generator.engine.ast.VariableExpr; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicServiceConfig; @@ -71,11 +70,11 @@ public void setUp() { @Test public void paramDefinitionsBlock_noConfigsFound() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); Service service = context.services().get(0); String jsonFilename = "retrying_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -99,11 +98,11 @@ public void paramDefinitionsBlock_noConfigsFound() { @Test public void paramDefinitionsBlock_basic() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); Service service = context.services().get(0); String jsonFilename = "showcase_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -154,7 +153,7 @@ public void codesDefinitionsBlock_noConfigsFound() { Service service = services.get(0); String jsonFilename = "retrying_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -191,7 +190,7 @@ public void codesDefinitionsBlock_basic() { Service service = services.get(0); String jsonFilename = "showcase_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -231,7 +230,7 @@ public void simpleBuilderExpr_basic() { Service service = services.get(0); String jsonFilename = "showcase_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -313,7 +312,7 @@ public void lroBuilderExpr() { Service service = services.get(0); String jsonFilename = "showcase_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional serviceConfigOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(serviceConfigOpt.isPresent()); GapicServiceConfig serviceConfig = serviceConfigOpt.get(); @@ -354,19 +353,19 @@ public void lroBuilderExpr() { @Test public void batchingSettings_minimalFlowControlSettings() { String filename = "pubsub_gapic.yaml"; - Path path = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, filename); + Path path = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), filename); Optional> batchingSettingsOpt = BatchingSettingsConfigParser.parse(Optional.of(path.toString())); assertTrue(batchingSettingsOpt.isPresent()); String jsonFilename = "pubsub_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional configOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(configOpt.isPresent()); GapicServiceConfig config = configOpt.get(); config.setBatchingSettings(batchingSettingsOpt); - GapicContext context = TestProtoLoaderUtil.parsePubSubPublisher(); + GapicContext context = TestProtoLoader.instance().parsePubSubPublisher(); Service service = context.services().get(0); assertEquals("Publisher", service.name()); @@ -408,19 +407,19 @@ public void batchingSettings_minimalFlowControlSettings() { @Test public void batchingSettings_fullFlowControlSettings() { String filename = "logging_gapic.yaml"; - Path path = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, filename); + Path path = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), filename); Optional> batchingSettingsOpt = BatchingSettingsConfigParser.parse(Optional.of(path.toString())); assertTrue(batchingSettingsOpt.isPresent()); String jsonFilename = "logging_grpc_service_config.json"; - Path jsonPath = Paths.get(ComposerConstants.TESTFILES_DIRECTORY, jsonFilename); + Path jsonPath = Paths.get(TestProtoLoader.instance().getTestFilesDirectory(), jsonFilename); Optional configOpt = ServiceConfigParser.parse(jsonPath.toString()); assertTrue(configOpt.isPresent()); GapicServiceConfig config = configOpt.get(); config.setBatchingSettings(batchingSettingsOpt); - GapicContext context = TestProtoLoaderUtil.parseLogging(); + GapicContext context = TestProtoLoader.instance().parseLogging(); Service service = context.services().get(0); assertEquals("LoggingServiceV2", service.name()); diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java similarity index 80% rename from src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java index 6c59d4c066..3510efaf3f 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/ServiceClientClassComposerTest.java @@ -12,12 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import static com.google.api.generator.test.framework.Assert.assertCodeEquals; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -29,20 +28,20 @@ public class ServiceClientClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, echoProtoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "EchoClient.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "EchoClient.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "EchoClient.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = TestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -50,13 +49,13 @@ public void generateServiceClasses_deprecated() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "DeprecatedServiceClient.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "DeprecatedServiceClient.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "DeprecatedServiceClient.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_methodSignatureHasNestedFields() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseIdentity(); + GapicContext context = TestProtoLoader.instance().parseShowcaseIdentity(); Service protoService = context.services().get(0); GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); @@ -64,7 +63,7 @@ public void generateServiceClasses_methodSignatureHasNestedFields() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "IdentityClient.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "IdentityClient.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "IdentityClient.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceStubClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java similarity index 81% rename from src/test/java/com/google/api/generator/gapic/composer/ServiceStubClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java index 739f806d9c..b30ce3630c 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceStubClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/ServiceStubClassComposerTest.java @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.common; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -28,20 +27,20 @@ public class ServiceStubClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = TestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceStubClassComposer.instance().generate(context, echoProtoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "EchoStub.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "EchoStub.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "EchoStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = TestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceStubClassComposer.instance().generate(context, protoService); @@ -49,7 +48,7 @@ public void generateServiceClasses_deprecated() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "DeprecatedServiceStub.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "DeprecatedServiceStub.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "DeprecatedServiceStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java b/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java index 681bcb9bef..5cd4ade9da 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java +++ b/src/test/java/com/google/api/generator/gapic/composer/common/TestProtoLoader.java @@ -17,14 +17,13 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; -import com.google.api.generator.gapic.composer.grpc.GrpcContext; import com.google.api.generator.gapic.model.GapicBatchingSettings; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.GapicServiceConfig; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.ResourceName; import com.google.api.generator.gapic.model.Service; -import com.google.api.generator.gapic.model.TransportContext; +import com.google.api.generator.gapic.model.Transport; import com.google.api.generator.gapic.protoparser.BatchingSettingsConfigParser; import com.google.api.generator.gapic.protoparser.Parser; import com.google.api.generator.gapic.protoparser.ServiceConfigParser; @@ -53,13 +52,13 @@ public class TestProtoLoader { private static final TestProtoLoader INSTANCE = new TestProtoLoader( - GrpcContext.instance(), "src/test/java/com/google/api/generator/gapic/testdata/"); + Transport.GRPC, "src/test/java/com/google/api/generator/gapic/testdata/"); private final String testFilesDirectory; - private final TransportContext transportContext; + private final Transport transport; - protected TestProtoLoader(TransportContext transportContext, String testFilesDirectory) { + protected TestProtoLoader(Transport transport, String testFilesDirectory) { this.testFilesDirectory = testFilesDirectory; - this.transportContext = transportContext; + this.transport = transport; } public static TestProtoLoader instance() { @@ -90,7 +89,7 @@ public GapicContext parseDeprecatedService() { .setServices(services) .setServiceConfig(config) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } @@ -118,7 +117,7 @@ public GapicContext parseShowcaseEcho() { .setServices(services) .setServiceConfig(config) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } @@ -139,7 +138,7 @@ public GapicContext parseShowcaseIdentity() { .setResourceNames(resourceNames) .setServices(services) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } @@ -164,7 +163,7 @@ public GapicContext parseShowcaseTesting() { .setResourceNames(resourceNames) .setServices(services) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } @@ -207,7 +206,7 @@ public GapicContext parsePubSubPublisher() { .setServices(services) .setServiceConfig(config) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } @@ -262,7 +261,7 @@ public GapicContext parseLogging() { .setServices(services) .setServiceConfig(config) .setHelperResourceNames(outputResourceNames) - .setTransportContext(transportContext) + .setTransport(transport) .build(); } diff --git a/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BUILD.bazel new file mode 100644 index 0000000000..85ac1a519e --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BUILD.bazel @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "goldens_files", + srcs = glob(["*.golden"]), +) diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/BatchingDescriptorComposerTestNoSubresponse.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BatchingDescriptorComposerTestNoSubresponse.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/BatchingDescriptorComposerTestNoSubresponse.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/BatchingDescriptorComposerTestNoSubresponse.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/BatchingDescriptorComposerTestSubresponse.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/BatchingDescriptorComposerTestSubresponse.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/BatchingDescriptorComposerTestSubresponse.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/BatchingDescriptorComposerTestSubresponse.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClient.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceStub.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/DeprecatedServiceStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/EchoStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/EchoStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden b/src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/IdentityClient.golden rename to src/test/java/com/google/api/generator/gapic/composer/common/goldens/IdentityClient.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/constants/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/constants/BUILD.bazel index c83471c30b..e69de29bb2 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/constants/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/constants/BUILD.bazel @@ -1,13 +0,0 @@ -load("@rules_java//java:defs.bzl", "java_binary") - -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "constants_files", - srcs = glob(["*.java"]), -) - -java_binary( - name = "constants", - srcs = ["constants_files"], -) diff --git a/src/test/java/com/google/api/generator/gapic/composer/constants/ComposerConstants.java b/src/test/java/com/google/api/generator/gapic/composer/constants/ComposerConstants.java deleted file mode 100644 index c8247b10eb..0000000000 --- a/src/test/java/com/google/api/generator/gapic/composer/constants/ComposerConstants.java +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.api.generator.gapic.composer.constants; - -public class ComposerConstants { - public static final String GOLDENFILES_DIRECTORY = - "src/test/java/com/google/api/generator/gapic/composer/goldens/"; - public static final String TESTFILES_DIRECTORY = - "src/test/java/com/google/api/generator/gapic/testdata/"; -} diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClientTest.golden deleted file mode 100644 index 9af83eb743..0000000000 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceClientTest.golden +++ /dev/null @@ -1,234 +0,0 @@ -package com.google.testdata.v1; - -import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.rpc.UnaryCallable; -import com.google.protobuf.Empty; -import com.google.testdata.v1.stub.DeprecatedServiceStub; -import com.google.testdata.v1.stub.DeprecatedServiceStubSettings; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import javax.annotation.Generated; - -// AUTO-GENERATED DOCUMENTATION AND CLASS. -/** - * This class provides the ability to make remote calls to the backing service through method calls - * that map to API methods. Sample code to get started: - * - *
{@code
- * try (DeprecatedServiceClient deprecatedServiceClient = DeprecatedServiceClient.create()) {
- *   FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build();
- *   deprecatedServiceClient.fastFibonacci(request);
- * }
- * }
- * - *

Note: close() needs to be called on the DeprecatedServiceClient object to clean up resources - * such as threads. In the example above, try-with-resources is used, which automatically calls - * close(). - * - *

The surface of this class includes several types of Java methods for each of the API's - * methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available as - * parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request object, - * which must be constructed before the call. Not every API method will have a request object - * method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable API - * callable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist with - * these names, this class includes a format method for each type of name, and additionally a parse - * method to extract the individual identifiers contained within names that are returned. - * - *

This class can be customized by passing in a custom instance of DeprecatedServiceSettings to - * create(). For example: - * - *

To customize credentials: - * - *

{@code
- * DeprecatedServiceSettings deprecatedServiceSettings =
- *     DeprecatedServiceSettings.newBuilder()
- *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
- *         .build();
- * DeprecatedServiceClient deprecatedServiceClient =
- *     DeprecatedServiceClient.create(deprecatedServiceSettings);
- * }
- * - *

To customize the endpoint: - * - *

{@code
- * DeprecatedServiceSettings deprecatedServiceSettings =
- *     DeprecatedServiceSettings.newBuilder().setEndpoint(myEndpoint).build();
- * DeprecatedServiceClient deprecatedServiceClient =
- *     DeprecatedServiceClient.create(deprecatedServiceSettings);
- * }
- * - *

Please refer to the GitHub repository's samples for more quickstart code snippets. - * - * @deprecated This class is deprecated and will be removed in the next major version update. - */ -@Deprecated -@Generated("by gapic-generator-java") -public class DeprecatedServiceClient implements BackgroundResource { - private final DeprecatedServiceSettings settings; - private final DeprecatedServiceStub stub; - - /** Constructs an instance of DeprecatedServiceClient with default settings. */ - public static final DeprecatedServiceClient create() throws IOException { - return create(DeprecatedServiceSettings.newBuilder().build()); - } - - /** - * Constructs an instance of DeprecatedServiceClient, using the given settings. The channels are - * created based on the settings passed in, or defaults for any settings that are not set. - */ - public static final DeprecatedServiceClient create(DeprecatedServiceSettings settings) - throws IOException { - return new DeprecatedServiceClient(settings); - } - - /** - * Constructs an instance of DeprecatedServiceClient, using the given stub for making calls. This - * is for advanced usage - prefer using create(DeprecatedServiceSettings). - */ - @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - public static final DeprecatedServiceClient create(DeprecatedServiceStub stub) { - return new DeprecatedServiceClient(stub); - } - - /** - * Constructs an instance of DeprecatedServiceClient, using the given settings. This is protected - * so that it is easy to make a subclass, but otherwise, the static factory methods should be - * preferred. - */ - protected DeprecatedServiceClient(DeprecatedServiceSettings settings) throws IOException { - this.settings = settings; - this.stub = ((DeprecatedServiceStubSettings) settings.getStubSettings()).createStub(); - } - - @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - protected DeprecatedServiceClient(DeprecatedServiceStub stub) { - this.settings = null; - this.stub = stub; - } - - public final DeprecatedServiceSettings getSettings() { - return settings; - } - - @BetaApi("A restructuring of stub classes is planned, so this may break in the future") - public DeprecatedServiceStub getStub() { - return stub; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Sample code: - * - *

{@code
-   * try (DeprecatedServiceClient deprecatedServiceClient = DeprecatedServiceClient.create()) {
-   *   FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build();
-   *   deprecatedServiceClient.fastFibonacci(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final void fastFibonacci(FibonacciRequest request) { - fastFibonacciCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Sample code: - * - *
{@code
-   * try (DeprecatedServiceClient deprecatedServiceClient = DeprecatedServiceClient.create()) {
-   *   FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build();
-   *   ApiFuture future = deprecatedServiceClient.fastFibonacciCallable().futureCall(request);
-   *   // Do something.
-   *   future.get();
-   * }
-   * }
- */ - public final UnaryCallable fastFibonacciCallable() { - return stub.fastFibonacciCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Sample code: - * - *
{@code
-   * try (DeprecatedServiceClient deprecatedServiceClient = DeprecatedServiceClient.create()) {
-   *   FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build();
-   *   deprecatedServiceClient.slowFibonacci(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - * @deprecated This method is deprecated and will be removed in the next major version update. - */ - @Deprecated - public final void slowFibonacci(FibonacciRequest request) { - slowFibonacciCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Sample code: - * - *
{@code
-   * try (DeprecatedServiceClient deprecatedServiceClient = DeprecatedServiceClient.create()) {
-   *   FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build();
-   *   ApiFuture future = deprecatedServiceClient.slowFibonacciCallable().futureCall(request);
-   *   // Do something.
-   *   future.get();
-   * }
-   * }
- * - * @deprecated This method is deprecated and will be removed in the next major version update. - */ - @Deprecated - public final UnaryCallable slowFibonacciCallable() { - return stub.slowFibonacciCallable(); - } - - @Override - public final void close() { - stub.close(); - } - - @Override - public void shutdown() { - stub.shutdown(); - } - - @Override - public boolean isShutdown() { - return stub.isShutdown(); - } - - @Override - public boolean isTerminated() { - return stub.isTerminated(); - } - - @Override - public void shutdownNow() { - stub.shutdownNow(); - } - - @Override - public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException { - return stub.awaitTermination(duration, unit); - } -} diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel index 3c86b19ea2..8c0cabe5a1 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/BUILD.bazel @@ -4,7 +4,13 @@ load("//:rules_bazel/java/java_diff_test.bzl", "golden_update") package(default_visibility = ["//visibility:public"]) TESTS = [ + "GrpcServiceCallableFactoryClassComposerTest", + "GrpcServiceStubClassComposerTest", + "MockServiceClassComposerTest", + "MockServiceImplClassComposerTest", + "ServiceClientTestClassComposerTest", "ServiceSettingsClassComposerTest", + "ServiceStubSettingsClassComposerTest", ] COMMON_SRCS = [ @@ -63,6 +69,7 @@ java_proto_library( [java_test( name = test_name, + size = "medium", srcs = [ "{0}.java".format(test_name), ] + COMMON_SRCS, diff --git a/src/test/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposerTest.java similarity index 82% rename from src/test/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposerTest.java index 8d0f5f9439..3f90ae955f 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/GrpcServiceCallableFactoryClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceCallableFactoryClassComposerTest.java @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -28,7 +27,7 @@ public class GrpcServiceCallableFactoryClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = GrpcServiceCallableFactoryClassComposer.instance().generate(context, echoProtoService); @@ -37,13 +36,13 @@ public void generateServiceClasses() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "GrpcEchoCallableFactory.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcEchoCallableFactory.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcEchoCallableFactory.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = GrpcServiceCallableFactoryClassComposer.instance().generate(context, protoService); @@ -54,7 +53,7 @@ public void generateServiceClasses_deprecated() { this.getClass(), "GrpcDeprecatedServiceCallableFactory.golden", visitor.write()); Path goldenFilePath = Paths.get( - ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcDeprecatedServiceCallableFactory.golden"); + Utils.getGoldenDir(this.getClass()), "GrpcDeprecatedServiceCallableFactory.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposerTest.java similarity index 79% rename from src/test/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposerTest.java index 4aa49a2f62..8ccbc442ed 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/GrpcServiceStubClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcServiceStubClassComposerTest.java @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -28,20 +27,20 @@ public class GrpcServiceStubClassComposerTest { @Test public void generateGrpcServiceStubClass_simple() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = GrpcServiceStubClassComposer.instance().generate(context, echoProtoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "GrpcEchoStub.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcEchoStub.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcEchoStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateGrpcServiceStubClass_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = GrpcServiceStubClassComposer.instance().generate(context, protoService); @@ -49,13 +48,13 @@ public void generateGrpcServiceStubClass_deprecated() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "GrpcDeprecatedServiceStub.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcDeprecatedServiceStub.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcDeprecatedServiceStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateGrpcServiceStubClass_httpBindings() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseTesting(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseTesting(); Service testingProtoService = context.services().get(0); GapicClass clazz = GrpcServiceStubClassComposer.instance().generate(context, testingProtoService); @@ -64,13 +63,13 @@ public void generateGrpcServiceStubClass_httpBindings() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "GrpcTestingStub.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcTestingStub.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcTestingStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateGrpcServiceStubClass_httpBindingsWithSubMessageFields() { - GapicContext context = TestProtoLoaderUtil.parsePubSubPublisher(); + GapicContext context = GrpcTestProtoLoader.instance().parsePubSubPublisher(); Service service = context.services().get(0); GapicClass clazz = GrpcServiceStubClassComposer.instance().generate(context, service); @@ -78,7 +77,7 @@ public void generateGrpcServiceStubClass_httpBindingsWithSubMessageFields() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "GrpcPublisherStub.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "GrpcPublisherStub.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "GrpcPublisherStub.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcTestProtoLoader.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcTestProtoLoader.java index f9c261ce60..ecc9206e40 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcTestProtoLoader.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/GrpcTestProtoLoader.java @@ -15,12 +15,13 @@ package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.gapic.composer.common.TestProtoLoader; +import com.google.api.generator.gapic.model.Transport; public class GrpcTestProtoLoader extends TestProtoLoader { - private static GrpcTestProtoLoader INSTANCE = new GrpcTestProtoLoader(); + private static final GrpcTestProtoLoader INSTANCE = new GrpcTestProtoLoader(); protected GrpcTestProtoLoader() { - super(GrpcContext.instance(), "src/test/java/com/google/api/generator/gapic/testdata/"); + super(Transport.GRPC, "src/test/java/com/google/api/generator/gapic/testdata/"); } public static GrpcTestProtoLoader instance() { diff --git a/src/test/java/com/google/api/generator/gapic/composer/MockServiceClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposerTest.java similarity index 81% rename from src/test/java/com/google/api/generator/gapic/composer/MockServiceClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposerTest.java index 5126817fdb..b8f17b5934 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/MockServiceClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceClassComposerTest.java @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -28,20 +27,20 @@ public class MockServiceClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = MockServiceClassComposer.instance().generate(context, echoProtoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "MockEcho.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "MockEcho.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "MockEcho.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = MockServiceClassComposer.instance().generate(context, protoService); @@ -49,7 +48,7 @@ public void generateServiceClasses_deprecated() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "MockDeprecatedService.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "MockDeprecatedService.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "MockDeprecatedService.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposerTest.java similarity index 81% rename from src/test/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposerTest.java index a4464ad1c5..854d0772dd 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/MockServiceImplClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/MockServiceImplClassComposerTest.java @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -28,20 +27,20 @@ public class MockServiceImplClassComposerTest { @Test public void generateServiceClasses() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = MockServiceImplClassComposer.instance().generate(context, echoProtoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "MockEchoImpl.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "MockEchoImpl.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "MockEchoImpl.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateServiceClasses_deprecated() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = MockServiceImplClassComposer.instance().generate(context, protoService); @@ -49,7 +48,7 @@ public void generateServiceClasses_deprecated() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "MockDeprecatedServiceImpl.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "MockDeprecatedServiceImpl.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "MockDeprecatedServiceImpl.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposerTest.java similarity index 77% rename from src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposerTest.java index d4932a1ace..cbb6bae23b 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceClientTestClassComposerTest.java @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import static com.google.api.generator.test.framework.Assert.assertCodeEquals; import static junit.framework.Assert.assertEquals; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; +import com.google.api.generator.gapic.composer.common.ServiceClientClassComposer; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; @@ -30,7 +30,7 @@ public class ServiceClientTestClassComposerTest { @Test public void generateClientTest_echoClient() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceClientTestClassComposer.instance().generate(context, echoProtoService); @@ -39,27 +39,27 @@ public void generateClientTest_echoClient() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "EchoClientTest.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "EchoClientTest.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "EchoClientTest.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateClientTest_deprecatedServiceClient() { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); - GapicClass clazz = ServiceClientClassComposer.instance().generate(context, protoService); + GapicClass clazz = ServiceClientTestClassComposer.instance().generate(context, protoService); JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "DeprecatedServiceClientTest.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "DeprecatedServiceClientTest.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "DeprecatedServiceClientTest.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateClientTest_testingClientResnameWithOnePatternWithNonSlashSepNames() { - GapicContext context = TestProtoLoaderUtil.parseShowcaseTesting(); + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseTesting(); Service testingProtoService = context.services().get(0); GapicClass clazz = ServiceClientTestClassComposer.instance().generate(context, testingProtoService); @@ -68,13 +68,13 @@ public void generateClientTest_testingClientResnameWithOnePatternWithNonSlashSep clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "TestingClientTest.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "TestingClientTest.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "TestingClientTest.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateClientTest_pubSubPublisherClient() { - GapicContext context = TestProtoLoaderUtil.parsePubSubPublisher(); + GapicContext context = GrpcTestProtoLoader.instance().parsePubSubPublisher(); Service subscriptionService = context.services().get(1); assertEquals("Subscriber", subscriptionService.name()); GapicClass clazz = @@ -84,13 +84,13 @@ public void generateClientTest_pubSubPublisherClient() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "SubscriberClientTest.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "SubscriberClientTest.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "SubscriberClientTest.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } @Test public void generateClientTest_logging() { - GapicContext context = TestProtoLoaderUtil.parseLogging(); + GapicContext context = GrpcTestProtoLoader.instance().parseLogging(); Service loggingService = context.services().get(0); GapicClass clazz = ServiceClientTestClassComposer.instance().generate(context, loggingService); @@ -98,7 +98,7 @@ public void generateClientTest_logging() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "LoggingClientTest.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "LoggingClientTest.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "LoggingClientTest.golden"); assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposerTest.java similarity index 75% rename from src/test/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposerTest.java rename to src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposerTest.java index 33a23fac52..3a907c432f 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceStubSettingsClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/ServiceStubSettingsClassComposerTest.java @@ -12,26 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.api.generator.gapic.composer; +package com.google.api.generator.gapic.composer.grpc; import static junit.framework.Assert.assertEquals; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.GapicContext; import com.google.api.generator.gapic.model.Service; import com.google.api.generator.test.framework.Assert; import com.google.api.generator.test.framework.Utils; -import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.Test; public class ServiceStubSettingsClassComposerTest { @Test - public void generateServiceStubSettingsClasses_batchingWithEmptyResponses() throws IOException { - GapicContext context = TestProtoLoaderUtil.parseLogging(); + public void generateServiceStubSettingsClasses_batchingWithEmptyResponses() { + GapicContext context = GrpcTestProtoLoader.instance().parseLogging(); Service protoService = context.services().get(0); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, protoService); @@ -40,14 +38,13 @@ public void generateServiceStubSettingsClasses_batchingWithEmptyResponses() thro Utils.saveCodegenToFile( this.getClass(), "LoggingServiceV2StubSettings.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "LoggingServiceV2StubSettings.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "LoggingServiceV2StubSettings.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test - public void generateServiceStubSettingsClasses_batchingWithNonemptyResponses() - throws IOException { - GapicContext context = TestProtoLoaderUtil.parsePubSubPublisher(); + public void generateServiceStubSettingsClasses_batchingWithNonemptyResponses() { + GapicContext context = GrpcTestProtoLoader.instance().parsePubSubPublisher(); Service protoService = context.services().get(0); assertEquals("Publisher", protoService.name()); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, protoService); @@ -56,13 +53,13 @@ public void generateServiceStubSettingsClasses_batchingWithNonemptyResponses() clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "PublisherStubSettings.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "PublisherStubSettings.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "PublisherStubSettings.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test - public void generateServiceStubSettingsClasses_basic() throws IOException { - GapicContext context = TestProtoLoaderUtil.parseShowcaseEcho(); + public void generateServiceStubSettingsClasses_basic() { + GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho(); Service echoProtoService = context.services().get(0); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, echoProtoService); @@ -71,13 +68,13 @@ public void generateServiceStubSettingsClasses_basic() throws IOException { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "EchoStubSettings.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "EchoStubSettings.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "EchoStubSettings.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @Test - public void generateServiceStubSettingsClasses_deprecated() throws IOException { - GapicContext context = TestProtoLoaderUtil.parseDeprecatedService(); + public void generateServiceStubSettingsClasses_deprecated() { + GapicContext context = GrpcTestProtoLoader.instance().parseDeprecatedService(); Service protoService = context.services().get(0); GapicClass clazz = ServiceStubSettingsClassComposer.instance().generate(context, protoService); @@ -86,7 +83,7 @@ public void generateServiceStubSettingsClasses_deprecated() throws IOException { Utils.saveCodegenToFile( this.getClass(), "DeprecatedServiceStubSettings.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "DeprecatedServiceStubSettings.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "DeprecatedServiceStubSettings.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClientTest.golden new file mode 100644 index 0000000000..bf7356d98c --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceClientTest.golden @@ -0,0 +1,130 @@ +package com.google.testdata.v1; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.GaxGrpcProperties; +import com.google.api.gax.grpc.testing.LocalChannelProvider; +import com.google.api.gax.grpc.testing.MockGrpcService; +import com.google.api.gax.grpc.testing.MockServiceHelper; +import com.google.api.gax.rpc.ApiClientHeaderProvider; +import com.google.api.gax.rpc.InvalidArgumentException; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.Empty; +import io.grpc.StatusRuntimeException; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import javax.annotation.Generated; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +@Generated("by gapic-generator-java") +public class DeprecatedServiceClientTest { + private static MockDeprecatedService mockDeprecatedService; + private static MockServiceHelper mockServiceHelper; + private DeprecatedServiceClient client; + private LocalChannelProvider channelProvider; + + @BeforeClass + public static void startStaticServer() { + mockDeprecatedService = new MockDeprecatedService(); + mockServiceHelper = + new MockServiceHelper( + UUID.randomUUID().toString(), Arrays.asList(mockDeprecatedService)); + mockServiceHelper.start(); + } + + @AfterClass + public static void stopServer() { + mockServiceHelper.stop(); + } + + @Before + public void setUp() throws IOException { + mockServiceHelper.reset(); + channelProvider = mockServiceHelper.createChannelProvider(); + DeprecatedServiceSettings settings = + DeprecatedServiceSettings.newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build(); + client = DeprecatedServiceClient.create(settings); + } + + @After + public void tearDown() throws Exception { + client.close(); + } + + @Test + public void fastFibonacciTest() throws Exception { + Empty expectedResponse = Empty.newBuilder().build(); + mockDeprecatedService.addResponse(expectedResponse); + + FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build(); + + client.fastFibonacci(request); + + List actualRequests = mockDeprecatedService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + FibonacciRequest actualRequest = ((FibonacciRequest) actualRequests.get(0)); + + Assert.assertEquals(request.getValue(), actualRequest.getValue()); + Assert.assertTrue( + channelProvider.isHeaderSent( + ApiClientHeaderProvider.getDefaultApiClientHeaderKey(), + GaxGrpcProperties.getDefaultApiClientHeaderPattern())); + } + + @Test + public void fastFibonacciExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT); + mockDeprecatedService.addException(exception); + + try { + FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build(); + client.fastFibonacci(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } + + @Test + public void slowFibonacciTest() throws Exception { + Empty expectedResponse = Empty.newBuilder().build(); + mockDeprecatedService.addResponse(expectedResponse); + + FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build(); + + client.slowFibonacci(request); + + List actualRequests = mockDeprecatedService.getRequests(); + Assert.assertEquals(1, actualRequests.size()); + FibonacciRequest actualRequest = ((FibonacciRequest) actualRequests.get(0)); + + Assert.assertEquals(request.getValue(), actualRequest.getValue()); + Assert.assertTrue( + channelProvider.isHeaderSent( + ApiClientHeaderProvider.getDefaultApiClientHeaderKey(), + GaxGrpcProperties.getDefaultApiClientHeaderPattern())); + } + + @Test + public void slowFibonacciExceptionTest() throws Exception { + StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT); + mockDeprecatedService.addException(exception); + + try { + FibonacciRequest request = FibonacciRequest.newBuilder().setValue(111972721).build(); + client.slowFibonacci(request); + Assert.fail("No exception raised"); + } catch (InvalidArgumentException e) { + // Expected exception. + } + } +} diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStubSettings.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/DeprecatedServiceStubSettings.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStubSettings.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClientTest.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClientTest.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClientTest.golden index fe7682e159..ba815b973f 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoClientTest.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoClientTest.golden @@ -40,8 +40,8 @@ import org.junit.Test; @Generated("by gapic-generator-java") public class EchoClientTest { - private static MockServiceHelper mockServiceHelper; private static MockEcho mockEcho; + private static MockServiceHelper mockServiceHelper; private EchoClient client; private LocalChannelProvider channelProvider; diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/EchoStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStubSettings.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/EchoStubSettings.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoStubSettings.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcDeprecatedServiceCallableFactory.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcDeprecatedServiceCallableFactory.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcDeprecatedServiceCallableFactory.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcDeprecatedServiceCallableFactory.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcDeprecatedServiceStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcDeprecatedServiceStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcDeprecatedServiceStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcDeprecatedServiceStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcEchoCallableFactory.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcEchoCallableFactory.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcEchoCallableFactory.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcEchoCallableFactory.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcEchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcEchoStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcEchoStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcEchoStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcPublisherStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcPublisherStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcPublisherStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcPublisherStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcTestingStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcTestingStub.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcTestingStub.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/GrpcTestingStub.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/LoggingClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/LoggingClientTest.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/LoggingClientTest.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/LoggingClientTest.golden index da4e0e0674..afa0414c65 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/LoggingClientTest.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/LoggingClientTest.golden @@ -43,8 +43,8 @@ import org.junit.Test; @Generated("by gapic-generator-java") public class LoggingServiceV2ClientTest { - private static MockServiceHelper mockServiceHelper; private static MockLoggingServiceV2 mockLoggingServiceV2; + private static MockServiceHelper mockServiceHelper; private LoggingServiceV2Client client; private LocalChannelProvider channelProvider; diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/LoggingServiceV2StubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/LoggingServiceV2StubSettings.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/LoggingServiceV2StubSettings.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/LoggingServiceV2StubSettings.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/MockDeprecatedService.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockDeprecatedService.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/MockDeprecatedService.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockDeprecatedService.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/MockDeprecatedServiceImpl.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockDeprecatedServiceImpl.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/MockDeprecatedServiceImpl.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockDeprecatedServiceImpl.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/MockEcho.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockEcho.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/MockEcho.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockEcho.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/MockEchoImpl.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockEchoImpl.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/MockEchoImpl.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/MockEchoImpl.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/PublisherStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/PublisherStubSettings.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/PublisherStubSettings.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/PublisherStubSettings.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/SubscriberClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/SubscriberClientTest.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/SubscriberClientTest.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/SubscriberClientTest.golden index 6871486078..941e4d1ea6 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/SubscriberClientTest.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/SubscriberClientTest.golden @@ -36,8 +36,8 @@ import org.junit.Test; @Generated("by gapic-generator-java") public class SubscriberClientTest { - private static MockServiceHelper mockServiceHelper; private static MockSubscriber mockSubscriber; + private static MockServiceHelper mockServiceHelper; private SubscriberClient client; private LocalChannelProvider channelProvider; diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/TestingClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/TestingClientTest.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/TestingClientTest.golden rename to src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/TestingClientTest.golden index f0dc05e18a..bb9c3e90b7 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/goldens/TestingClientTest.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/TestingClientTest.golden @@ -31,9 +31,9 @@ import org.junit.Test; @Generated("by gapic-generator-java") public class TestingClientTest { + private static MockTesting mockTesting; private static MockServiceHelper mockServiceHelper; private TestingClient client; - private static MockTesting mockTesting; private LocalChannelProvider channelProvider; @BeforeClass diff --git a/src/test/java/com/google/api/generator/gapic/composer/resourcename/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/resourcename/BUILD.bazel index 17b37c640b..a62cd2dad8 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/resourcename/BUILD.bazel +++ b/src/test/java/com/google/api/generator/gapic/composer/resourcename/BUILD.bazel @@ -1,9 +1,13 @@ load("@rules_java//java:defs.bzl", "java_proto_library", "java_test") +load("//:rules_bazel/java/java_diff_test.bzl", "golden_update") package(default_visibility = ["//visibility:public"]) -TESTS = [ +UPDATE_GOLDENS_TESTS = [ "ResourceNameHelperClassComposerTest", +] + +TESTS = UPDATE_GOLDENS_TESTS + [ "ResourceNameTokenizerTest", ] @@ -12,36 +16,37 @@ filegroup( srcs = ["{0}.java".format(f) for f in TESTS], ) +TEST_DEPS = [ + ":common_resources_java_proto", + "//src/main/java/com/google/api/generator/engine/ast", + "//src/main/java/com/google/api/generator/engine/writer", + "//src/main/java/com/google/api/generator/gapic/composer/resourcename", + "//src/main/java/com/google/api/generator/gapic/model", + "//src/main/java/com/google/api/generator/gapic/protoparser", + "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", + "//src/test/java/com/google/api/generator/test/framework:asserts", + "//src/test/java/com/google/api/generator/test/framework:utils", + "//src/test/java/com/google/api/generator/testutils", + "@com_google_api_api_common//jar", + "@com_google_api_gax_java//gax", + "@com_google_googleapis//google/logging/v2:logging_java_proto", + "@com_google_googleapis//google/rpc:rpc_java_proto", + "@com_google_guava_guava", + "@com_google_protobuf//:protobuf_java", + "@com_google_truth_truth//jar", + "@junit_junit//jar", +] + [java_test( name = test_name, srcs = ["{0}.java".format(test_name)], data = [ - "//src/test/java/com/google/api/generator/gapic/composer/goldens:goldens_files", + "//src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens:goldens_files", "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", ], test_class = "com.google.api.generator.gapic.composer.resourcename.{0}".format(test_name), - deps = [ - ":common_resources_java_proto", - "//src/main/java/com/google/api/generator/engine/ast", - "//src/main/java/com/google/api/generator/engine/writer", - "//src/main/java/com/google/api/generator/gapic/composer/resourcename", - "//src/main/java/com/google/api/generator/gapic/model", - "//src/main/java/com/google/api/generator/gapic/protoparser", - "//src/test/java/com/google/api/generator/gapic/composer/constants", - "//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto", - "//src/test/java/com/google/api/generator/test/framework:asserts", - "//src/test/java/com/google/api/generator/test/framework:utils", - "//src/test/java/com/google/api/generator/testutils", - "@com_google_api_api_common//jar", - "@com_google_api_gax_java//gax", - "@com_google_googleapis//google/logging/v2:logging_java_proto", - "@com_google_googleapis//google/rpc:rpc_java_proto", - "@com_google_guava_guava", - "@com_google_protobuf//:protobuf_java", - "@com_google_truth_truth//jar", - "@junit_junit//jar", - ], + deps = TEST_DEPS, ) for test_name in TESTS] java_proto_library( @@ -50,3 +55,21 @@ java_proto_library( "@com_google_googleapis//google/cloud:common_resources_proto", ], ) + +# Run `bazel run src/test/java/com/google/api/generator/gapic/composer/resourcename:testTargetName_update` +# to update goldens as expected generated code. +# `ServiceClient*` tests are not supported now since they are still in active development. + +[golden_update( + name = "{0}_update".format(test_name), + srcs = [ + "{0}.java".format(test_name), + ], + data = [ + "//src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens:goldens_files", + "//src/test/java/com/google/api/generator/gapic/testdata:gapic_config_files", + "//src/test/java/com/google/api/generator/gapic/testdata:service_config_files", + ], + test_class = "com.google.api.generator.gapic.composer.resourcename.{0}".format(test_name), + deps = TEST_DEPS, +) for test_name in UPDATE_GOLDENS_TESTS] diff --git a/src/test/java/com/google/api/generator/gapic/composer/resourcename/ResourceNameHelperClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/resourcename/ResourceNameHelperClassComposerTest.java index cd918c865d..16251dc124 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/resourcename/ResourceNameHelperClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/resourcename/ResourceNameHelperClassComposerTest.java @@ -18,7 +18,6 @@ import static junit.framework.Assert.assertEquals; import com.google.api.generator.engine.writer.JavaWriterVisitor; -import com.google.api.generator.gapic.composer.constants.ComposerConstants; import com.google.api.generator.gapic.model.GapicClass; import com.google.api.generator.gapic.model.Message; import com.google.api.generator.gapic.model.ResourceName; @@ -107,7 +106,7 @@ public void generateResourceNameClass_echoFoobarMultiplePatterns() { JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "FoobarName.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "FoobarName.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "FoobarName.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @@ -156,7 +155,7 @@ public void generateResourceNameClass_loggingOnePatternMultipleVariables() { clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "BillingAccountLocationName.golden", visitor.write()); Path goldenFilePath = - Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "BillingAccountLocationName.golden"); + Paths.get(Utils.getGoldenDir(this.getClass()), "BillingAccountLocationName.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @@ -185,7 +184,7 @@ public void generateResourceNameClass_testingSessionOnePattern() { JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "SessionName.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "SessionName.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "SessionName.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @@ -214,7 +213,7 @@ public void generateResourceNameClass_testingBlueprintPatternWithNonSlashSeparat JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "TestName.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "TestName.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "TestName.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } @@ -236,7 +235,7 @@ public void generateResourceNameClass_childSingleton() { JavaWriterVisitor visitor = new JavaWriterVisitor(); clazz.classDefinition().accept(visitor); Utils.saveCodegenToFile(this.getClass(), "AgentName.golden", visitor.write()); - Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "AgentName.golden"); + Path goldenFilePath = Paths.get(Utils.getGoldenDir(this.getClass()), "AgentName.golden"); Assert.assertCodeEquals(goldenFilePath, visitor.write()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/AgentName.golden b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/AgentName.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/AgentName.golden rename to src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/AgentName.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BUILD.bazel b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BUILD.bazel new file mode 100644 index 0000000000..85ac1a519e --- /dev/null +++ b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BUILD.bazel @@ -0,0 +1,6 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "goldens_files", + srcs = glob(["*.golden"]), +) diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/BillingAccountLocationName.golden b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BillingAccountLocationName.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/BillingAccountLocationName.golden rename to src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/BillingAccountLocationName.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/FoobarName.golden b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/FoobarName.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/FoobarName.golden rename to src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/FoobarName.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/SessionName.golden b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/SessionName.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/SessionName.golden rename to src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/SessionName.golden diff --git a/src/test/java/com/google/api/generator/gapic/composer/goldens/TestName.golden b/src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/TestName.golden similarity index 100% rename from src/test/java/com/google/api/generator/gapic/composer/goldens/TestName.golden rename to src/test/java/com/google/api/generator/gapic/composer/resourcename/goldens/TestName.golden diff --git a/test/integration/apis/kms/v1/cloudkms_test_mixins_v1.yaml b/test/integration/apis/kms/v1/cloudkms_test_mixins_v1.yaml index 4190b62d0b..2828ca13f0 100644 --- a/test/integration/apis/kms/v1/cloudkms_test_mixins_v1.yaml +++ b/test/integration/apis/kms/v1/cloudkms_test_mixins_v1.yaml @@ -21,6 +21,7 @@ documentation: Gets the access control policy for a resource. Returns an empty policy if the resource exists and does not have a policy set. + # This RPC shouldn't appear in the proto even though the documentation field is set. - selector: google.iam.v1.IAMPolicy.SetIamPolicy description: |- Sets the access control policy on the specified resource. Replaces @@ -29,31 +30,37 @@ documentation: Can return `NOT_FOUND`, `INVALID_ARGUMENT`, and `PERMISSION_DENIED` errors. + # Test the overriding of comments. - selector: google.iam.v1.IAMPolicy.TestIamPermissions description: |- - Returns permissions that a caller has on the specified resource. If the - resource does not exist, this will return an empty set of - permissions, not a `NOT_FOUND` error. - - Note: This operation is designed to be used for building - permission-aware UIs and command-line tools, not for authorization - checking. This operation may "fail open" without warning. + This is a different comment for TestIamPermissions in the yaml file that should clobber the documentation in iam_policy.proto. http: rules: + - selector: google.cloud.location.Locations.GetLocation + get: "/v1/{name=locations/*}" + body: '*' + # Test different HTTP verbs. + - selector: google.cloud.location.Locations.ListLocations + get: "/v1/{filter=*/*}/locations" + body: '*' + additional_bindings: + - post: '/v1/{page_size=*}' + body: '*' - selector: google.iam.v1.IAMPolicy.GetIamPolicy get: '/v1/{resource=projects/*/locations/*/keyRings/*}:getIamPolicy' additional_bindings: - get: '/v1/{resource=projects/*/locations/*/keyRings/*/cryptoKeys/*}:getIamPolicy' - get: '/v1/{resource=projects/*/locations/*/keyRings/*/importJobs/*}:getIamPolicy' - - selector: google.iam.v1.IAMPolicy.SetIamPolicy - post: '/v1/{resource=projects/*/locations/*/keyRings/*}:setIamPolicy' - body: '*' - additional_bindings: - - post: '/v1/{resource=projects/*/locations/*/keyRings/*/cryptoKeys/*}:setIamPolicy' - body: '*' - - post: '/v1/{resource=projects/*/locations/*/keyRings/*/importJobs/*}:setIamPolicy' - body: '*' + # Test the omission of SetIamPolicy - this should no longer appear in the generated client. +# - selector: google.iam.v1.IAMPolicy.SetIamPolicy +# post: '/v1/{resource=projects/*/locations/*/keyRings/*}:setIamPolicy' +# body: '*' +# additional_bindings: +# - post: '/v1/{resource=projects/*/locations/*/keyRings/*/cryptoKeys/*}:setIamPolicy' +# body: '*' +# - post: '/v1/{resource=projects/*/locations/*/keyRings/*/importJobs/*}:setIamPolicy' +# body: '*' - selector: google.iam.v1.IAMPolicy.TestIamPermissions post: '/v1/{resource=projects/*/locations/*/keyRings/*}:testIamPermissions' body: '*' diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClient.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClient.java index 19ddbcd661..cc3e563cff 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClient.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClient.java @@ -36,7 +36,6 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import com.google.protobuf.ByteString; @@ -3334,62 +3333,8 @@ public final UnaryCallable getLocationCallable() { // AUTO-GENERATED DOCUMENTATION AND METHOD. /** - * Sets the access control policy on the specified resource. Replaces any existing policy. - * - *

Sample code: - * - *

{@code
-   * try (KeyManagementServiceClient keyManagementServiceClient =
-   *     KeyManagementServiceClient.create()) {
-   *   SetIamPolicyRequest request =
-   *       SetIamPolicyRequest.newBuilder()
-   *           .setResource(KeyRingName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]").toString())
-   *           .setPolicy(Policy.newBuilder().build())
-   *           .build();
-   *   Policy response = keyManagementServiceClient.setIamPolicy(request);
-   * }
-   * }
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.rpc.ApiException if the remote call fails - */ - public final Policy setIamPolicy(SetIamPolicyRequest request) { - return setIamPolicyCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Sets the access control policy on the specified resource. Replaces any existing policy. - * - *

Sample code: - * - *

{@code
-   * try (KeyManagementServiceClient keyManagementServiceClient =
-   *     KeyManagementServiceClient.create()) {
-   *   SetIamPolicyRequest request =
-   *       SetIamPolicyRequest.newBuilder()
-   *           .setResource(KeyRingName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]").toString())
-   *           .setPolicy(Policy.newBuilder().build())
-   *           .build();
-   *   ApiFuture future =
-   *       keyManagementServiceClient.setIamPolicyCallable().futureCall(request);
-   *   // Do something.
-   *   Policy response = future.get();
-   * }
-   * }
- */ - public final UnaryCallable setIamPolicyCallable() { - return stub.setIamPolicyCallable(); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD. - /** - * Returns permissions that a caller has on the specified resource. If the resource does not - * exist, this will return an empty set of permissions, not a NOT_FOUND error. - * - *

Note: This operation is designed to be used for building permission-aware UIs and - * command-line tools, not for authorization checking. This operation may "fail open" without - * warning. + * This is a different comment for TestIamPermissions in the yaml file that should clobber the + * documentation in iam_policy.proto. * *

Sample code: * @@ -3414,12 +3359,8 @@ public final TestIamPermissionsResponse testIamPermissions(TestIamPermissionsReq // AUTO-GENERATED DOCUMENTATION AND METHOD. /** - * Returns permissions that a caller has on the specified resource. If the resource does not - * exist, this will return an empty set of permissions, not a NOT_FOUND error. - * - *

Note: This operation is designed to be used for building permission-aware UIs and - * command-line tools, not for authorization checking. This operation may "fail open" without - * warning. + * This is a different comment for TestIamPermissions in the yaml file that should clobber the + * documentation in iam_policy.proto. * *

Sample code: * diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClientTest.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClientTest.java index 0d02ab2526..b1952fc8e3 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClientTest.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceClientTest.java @@ -41,7 +41,6 @@ import com.google.iam.v1.GetPolicyOptions; import com.google.iam.v1.MockIAMPolicy; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import com.google.protobuf.AbstractMessage; @@ -77,12 +76,12 @@ public class KeyManagementServiceClientTest { @BeforeClass public static void startStaticServer() { mockKeyManagementService = new MockKeyManagementService(); - mockLocations = new MockLocations(); mockIAMPolicy = new MockIAMPolicy(); + mockLocations = new MockLocations(); mockServiceHelper = new MockServiceHelper( UUID.randomUUID().toString(), - Arrays.asList(mockKeyManagementService, mockLocations, mockIAMPolicy)); + Arrays.asList(mockKeyManagementService, mockIAMPolicy, mockLocations)); mockServiceHelper.start(); } @@ -2374,55 +2373,6 @@ public void getLocationExceptionTest() throws Exception { } } - @Test - public void setIamPolicyTest() throws Exception { - Policy expectedResponse = - Policy.newBuilder() - .setVersion(351608024) - .addAllBindings(new ArrayList()) - .setEtag(ByteString.EMPTY) - .build(); - mockIAMPolicy.addResponse(expectedResponse); - - SetIamPolicyRequest request = - SetIamPolicyRequest.newBuilder() - .setResource(KeyRingName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]").toString()) - .setPolicy(Policy.newBuilder().build()) - .build(); - - Policy actualResponse = client.setIamPolicy(request); - Assert.assertEquals(expectedResponse, actualResponse); - - List actualRequests = mockIAMPolicy.getRequests(); - Assert.assertEquals(1, actualRequests.size()); - SetIamPolicyRequest actualRequest = ((SetIamPolicyRequest) actualRequests.get(0)); - - Assert.assertEquals(request.getResource(), actualRequest.getResource()); - Assert.assertEquals(request.getPolicy(), actualRequest.getPolicy()); - Assert.assertTrue( - channelProvider.isHeaderSent( - ApiClientHeaderProvider.getDefaultApiClientHeaderKey(), - GaxGrpcProperties.getDefaultApiClientHeaderPattern())); - } - - @Test - public void setIamPolicyExceptionTest() throws Exception { - StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT); - mockIAMPolicy.addException(exception); - - try { - SetIamPolicyRequest request = - SetIamPolicyRequest.newBuilder() - .setResource(KeyRingName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]").toString()) - .setPolicy(Policy.newBuilder().build()) - .build(); - client.setIamPolicy(request); - Assert.fail("No exception raised"); - } catch (InvalidArgumentException e) { - // Expected exception. - } - } - @Test public void testIamPermissionsTest() throws Exception { TestIamPermissionsResponse expectedResponse = diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceSettings.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceSettings.java index bf38dcd54e..d749c91145 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceSettings.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/KeyManagementServiceSettings.java @@ -41,7 +41,6 @@ import com.google.cloud.location.Location; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import java.io.IOException; @@ -233,11 +232,6 @@ public UnaryCallSettings getLocationSettings() { return ((KeyManagementServiceStubSettings) getStubSettings()).getLocationSettings(); } - /** Returns the object with the settings used for calls to setIamPolicy. */ - public UnaryCallSettings setIamPolicySettings() { - return ((KeyManagementServiceStubSettings) getStubSettings()).setIamPolicySettings(); - } - /** Returns the object with the settings used for calls to testIamPermissions. */ public UnaryCallSettings testIamPermissionsSettings() { @@ -494,11 +488,6 @@ public UnaryCallSettings.Builder getLocationSettin return getStubSettingsBuilder().getLocationSettings(); } - /** Returns the builder for the settings used for calls to setIamPolicy. */ - public UnaryCallSettings.Builder setIamPolicySettings() { - return getStubSettingsBuilder().setIamPolicySettings(); - } - /** Returns the builder for the settings used for calls to testIamPermissions. */ public UnaryCallSettings.Builder testIamPermissionsSettings() { diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/gapic_metadata.json b/test/integration/goldens/kms/com/google/cloud/kms/v1/gapic_metadata.json index a3c2c93ed7..73abe153f4 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/gapic_metadata.json +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/gapic_metadata.json @@ -79,9 +79,6 @@ "RestoreCryptoKeyVersion": { "methods": ["restoreCryptoKeyVersion", "restoreCryptoKeyVersion", "restoreCryptoKeyVersion", "restoreCryptoKeyVersionCallable"] }, - "SetIamPolicy": { - "methods": ["setIamPolicy", "setIamPolicyCallable"] - }, "TestIamPermissions": { "methods": ["testIamPermissions", "testIamPermissionsCallable"] }, diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/GrpcKeyManagementServiceStub.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/GrpcKeyManagementServiceStub.java index f2dcc16fa9..19065361ed 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/GrpcKeyManagementServiceStub.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/GrpcKeyManagementServiceStub.java @@ -72,7 +72,6 @@ import com.google.common.collect.ImmutableMap; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import com.google.longrunning.stub.GrpcOperationsStub; @@ -345,14 +344,6 @@ public class GrpcKeyManagementServiceStub extends KeyManagementServiceStub { .setResponseMarshaller(ProtoUtils.marshaller(Location.getDefaultInstance())) .build(); - private static final MethodDescriptor setIamPolicyMethodDescriptor = - MethodDescriptor.newBuilder() - .setType(MethodDescriptor.MethodType.UNARY) - .setFullMethodName("google.iam.v1.IAMPolicy/SetIamPolicy") - .setRequestMarshaller(ProtoUtils.marshaller(SetIamPolicyRequest.getDefaultInstance())) - .setResponseMarshaller(ProtoUtils.marshaller(Policy.getDefaultInstance())) - .build(); - private static final MethodDescriptor testIamPermissionsMethodDescriptor = MethodDescriptor.newBuilder() @@ -409,7 +400,6 @@ public class GrpcKeyManagementServiceStub extends KeyManagementServiceStub { private final UnaryCallable listLocationsPagedCallable; private final UnaryCallable getLocationCallable; - private final UnaryCallable setIamPolicyCallable; private final UnaryCallable testIamPermissionsCallable; @@ -793,7 +783,8 @@ public Map extract(GetIamPolicyRequest request) { @Override public Map extract(ListLocationsRequest request) { ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("name", String.valueOf(request.getName())); + params.put("filter", String.valueOf(request.getFilter())); + params.put("page_size", String.valueOf(request.getPageSize())); return params.build(); } }) @@ -811,19 +802,6 @@ public Map extract(GetLocationRequest request) { } }) .build(); - GrpcCallSettings setIamPolicyTransportSettings = - GrpcCallSettings.newBuilder() - .setMethodDescriptor(setIamPolicyMethodDescriptor) - .setParamsExtractor( - new RequestParamsExtractor() { - @Override - public Map extract(SetIamPolicyRequest request) { - ImmutableMap.Builder params = ImmutableMap.builder(); - params.put("resource", String.valueOf(request.getResource())); - return params.build(); - } - }) - .build(); GrpcCallSettings testIamPermissionsTransportSettings = GrpcCallSettings.newBuilder() @@ -952,9 +930,6 @@ public Map extract(TestIamPermissionsRequest request) { this.getLocationCallable = callableFactory.createUnaryCallable( getLocationTransportSettings, settings.getLocationSettings(), clientContext); - this.setIamPolicyCallable = - callableFactory.createUnaryCallable( - setIamPolicyTransportSettings, settings.setIamPolicySettings(), clientContext); this.testIamPermissionsCallable = callableFactory.createUnaryCallable( testIamPermissionsTransportSettings, @@ -1136,11 +1111,6 @@ public UnaryCallable getLocationCallable() { return getLocationCallable; } - @Override - public UnaryCallable setIamPolicyCallable() { - return setIamPolicyCallable; - } - @Override public UnaryCallable testIamPermissionsCallable() { diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStub.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStub.java index 3c6cb33625..14915e1ae7 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStub.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStub.java @@ -66,7 +66,6 @@ import com.google.cloud.location.Location; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import javax.annotation.Generated; @@ -218,10 +217,6 @@ public UnaryCallable getLocationCallable() { throw new UnsupportedOperationException("Not implemented: getLocationCallable()"); } - public UnaryCallable setIamPolicyCallable() { - throw new UnsupportedOperationException("Not implemented: setIamPolicyCallable()"); - } - public UnaryCallable testIamPermissionsCallable() { throw new UnsupportedOperationException("Not implemented: testIamPermissionsCallable()"); diff --git a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStubSettings.java b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStubSettings.java index dc9718e802..5ebc43167f 100644 --- a/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStubSettings.java +++ b/test/integration/goldens/kms/com/google/cloud/kms/v1/stub/KeyManagementServiceStubSettings.java @@ -90,7 +90,6 @@ import com.google.common.collect.Lists; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; -import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import java.io.IOException; @@ -188,7 +187,6 @@ public class KeyManagementServiceStubSettings ListLocationsRequest, ListLocationsResponse, ListLocationsPagedResponse> listLocationsSettings; private final UnaryCallSettings getLocationSettings; - private final UnaryCallSettings setIamPolicySettings; private final UnaryCallSettings testIamPermissionsSettings; @@ -619,11 +617,6 @@ public UnaryCallSettings getLocationSettings() { return getLocationSettings; } - /** Returns the object with the settings used for calls to setIamPolicy. */ - public UnaryCallSettings setIamPolicySettings() { - return setIamPolicySettings; - } - /** Returns the object with the settings used for calls to testIamPermissions. */ public UnaryCallSettings testIamPermissionsSettings() { @@ -726,7 +719,6 @@ protected KeyManagementServiceStubSettings(Builder settingsBuilder) throws IOExc getIamPolicySettings = settingsBuilder.getIamPolicySettings().build(); listLocationsSettings = settingsBuilder.listLocationsSettings().build(); getLocationSettings = settingsBuilder.getLocationSettings().build(); - setIamPolicySettings = settingsBuilder.setIamPolicySettings().build(); testIamPermissionsSettings = settingsBuilder.testIamPermissionsSettings().build(); } @@ -784,7 +776,6 @@ public static class Builder ListLocationsRequest, ListLocationsResponse, ListLocationsPagedResponse> listLocationsSettings; private final UnaryCallSettings.Builder getLocationSettings; - private final UnaryCallSettings.Builder setIamPolicySettings; private final UnaryCallSettings.Builder testIamPermissionsSettings; private static final ImmutableMap> @@ -867,7 +858,6 @@ protected Builder(ClientContext clientContext) { getIamPolicySettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); listLocationsSettings = PagedCallSettings.newBuilder(LIST_LOCATIONS_PAGE_STR_FACT); getLocationSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); - setIamPolicySettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); testIamPermissionsSettings = UnaryCallSettings.newUnaryCallSettingsBuilder(); unaryMethodSettingsBuilders = @@ -898,7 +888,6 @@ protected Builder(ClientContext clientContext) { getIamPolicySettings, listLocationsSettings, getLocationSettings, - setIamPolicySettings, testIamPermissionsSettings); initDefaults(this); } @@ -933,7 +922,6 @@ protected Builder(KeyManagementServiceStubSettings settings) { getIamPolicySettings = settings.getIamPolicySettings.toBuilder(); listLocationsSettings = settings.listLocationsSettings.toBuilder(); getLocationSettings = settings.getLocationSettings.toBuilder(); - setIamPolicySettings = settings.setIamPolicySettings.toBuilder(); testIamPermissionsSettings = settings.testIamPermissionsSettings.toBuilder(); unaryMethodSettingsBuilders = @@ -964,7 +952,6 @@ protected Builder(KeyManagementServiceStubSettings settings) { getIamPolicySettings, listLocationsSettings, getLocationSettings, - setIamPolicySettings, testIamPermissionsSettings); } @@ -1110,11 +1097,6 @@ private static Builder initDefaults(Builder builder) { .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_codes")) .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_params")); - builder - .setIamPolicySettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) - .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_1_params")); - builder .testIamPermissionsSettings() .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_1_codes")) @@ -1290,11 +1272,6 @@ public UnaryCallSettings.Builder getLocationSettin return getLocationSettings; } - /** Returns the builder for the settings used for calls to setIamPolicy. */ - public UnaryCallSettings.Builder setIamPolicySettings() { - return setIamPolicySettings; - } - /** Returns the builder for the settings used for calls to testIamPermissions. */ public UnaryCallSettings.Builder testIamPermissionsSettings() { diff --git a/test/integration/goldens/kms/com/google/iam/v1/MockIAMPolicyImpl.java b/test/integration/goldens/kms/com/google/iam/v1/MockIAMPolicyImpl.java index fc661c900c..6245f271c9 100644 --- a/test/integration/goldens/kms/com/google/iam/v1/MockIAMPolicyImpl.java +++ b/test/integration/goldens/kms/com/google/iam/v1/MockIAMPolicyImpl.java @@ -58,26 +58,6 @@ public void reset() { responses = new LinkedList<>(); } - @Override - public void setIamPolicy(SetIamPolicyRequest request, StreamObserver responseObserver) { - Object response = responses.poll(); - if (response instanceof Policy) { - requests.add(request); - responseObserver.onNext(((Policy) response)); - responseObserver.onCompleted(); - } else if (response instanceof Exception) { - responseObserver.onError(((Exception) response)); - } else { - responseObserver.onError( - new IllegalArgumentException( - String.format( - "Unrecognized response type %s for method SetIamPolicy, expected %s or %s", - response == null ? "null" : response.getClass().getName(), - Policy.class.getName(), - Exception.class.getName()))); - } - } - @Override public void getIamPolicy(GetIamPolicyRequest request, StreamObserver responseObserver) { Object response = responses.poll(); diff --git a/version.txt b/version.txt index 90a27f9cea..af0b7ddbff 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0.5 +1.0.6