diff --git a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java index 21ca7fa5fd..4fafe9b49b 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposer.java @@ -416,7 +416,8 @@ private static List createTestMethods( Map messageTypes) { List javaMethods = new ArrayList<>(); for (Method method : service.methods()) { - if (method.methodSignatures().isEmpty()) { + // Ignore variants for streaming methods as well. + if (method.methodSignatures().isEmpty() || !method.stream().equals(Method.Stream.NONE)) { javaMethods.add( createRpcTestMethod( method, @@ -489,6 +490,10 @@ private static MethodDefinition createRpcTestMethod( Map classMemberVarExprs, Map resourceNames, Map messageTypes) { + if (!method.stream().equals(Method.Stream.NONE)) { + return createStreamingRpcTestMethod( + method, serviceName, classMemberVarExprs, resourceNames, messageTypes); + } // Construct the expected response. // TODO(miraleung): Paging here. TypeNode methodOutputType = method.hasLro() ? method.lro().responseType() : method.outputType(); @@ -890,6 +895,242 @@ private static MethodDefinition createRpcTestMethod( .build(); } + private static MethodDefinition createStreamingRpcTestMethod( + Method method, + String serviceName, + Map classMemberVarExprs, + Map resourceNames, + Map messageTypes) { + TypeNode methodOutputType = method.hasLro() ? method.lro().responseType() : method.outputType(); + List methodExprs = new ArrayList<>(); + VariableExpr expectedResponseVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(methodOutputType).setName("expectedResponse").build()); + Expr expectedResponseValExpr = null; + if (messageTypes.containsKey(methodOutputType.reference().name())) { + expectedResponseValExpr = + DefaultValueComposer.createSimpleMessageBuilderExpr( + messageTypes.get(methodOutputType.reference().name()), 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(STATIC_TYPES.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(getMockServiceVarName(serviceName))) + .setMethodName("addResponse") + .setArguments(resultOperationVarExpr) + .build()); + } else { + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get(getMockServiceVarName(serviceName))) + .setMethodName("addResponse") + .setArguments(expectedResponseVarExpr) + .build()); + } + // TODO(miraleung): Empty line here. + + // Construct the request or method arguments. + VariableExpr requestVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(method.inputType()).setName("request").build()); + Message requestMessage = messageTypes.get(method.inputType().reference().name()); + Preconditions.checkNotNull(requestMessage); + Expr valExpr = + DefaultValueComposer.createSimpleMessageBuilderExpr( + requestMessage, resourceNames, messageTypes); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(requestVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(valExpr) + .build()); + + // Construct the mock stream observer. + VariableExpr responseObserverVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + STATIC_TYPES + .get("MockStreamObserver") + .reference() + .copyAndSetGenerics(Arrays.asList(method.outputType().reference())))) + .setName("responseObserver") + .build()); + + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(responseObserverVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + NewObjectExpr.builder() + .setType(STATIC_TYPES.get("MockStreamObserver")) + .setIsGeneric(true) + .build()) + .build()); + + // Build the callable variable and assign it. + VariableExpr callableVarExpr = + VariableExpr.withVariable( + Variable.builder().setType(getCallableType(method)).setName("callable").build()); + Expr streamingCallExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(classMemberVarExprs.get("client")) + .setMethodName(String.format("%sCallable", JavaStyle.toLowerCamelCase(method.name()))) + .setReturnType(callableVarExpr.type()) + .build(); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(callableVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(streamingCallExpr) + .build()); + + // Call the streaming-variant callable method. + if (method.stream().equals(Method.Stream.SERVER)) { + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(callableVarExpr) + .setMethodName("serverStreamingCall") + .setArguments(requestVarExpr, responseObserverVarExpr) + .build()); + } else { + VariableExpr requestObserverVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + STATIC_TYPES + .get("ApiStreamObserver") + .reference() + .copyAndSetGenerics(Arrays.asList(method.inputType().reference())))) + .setName("requestObserver") + .build()); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(requestObserverVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr( + MethodInvocationExpr.builder() + .setExprReferenceExpr(callableVarExpr) + .setMethodName(getCallableMethodName(method)) + .setArguments(requestVarExpr, responseObserverVarExpr) + .setReturnType(requestObserverVarExpr.type()) + .build()) + .build()); + + // TODO(miraleung): Empty line here. + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestObserverVarExpr) + .setMethodName("onNext") + .setArguments(requestVarExpr) + .build()); + methodExprs.add( + MethodInvocationExpr.builder() + .setExprReferenceExpr(requestObserverVarExpr) + .setMethodName("onCompleted") + .build()); + } + + // Check the actual responses. + VariableExpr actualResponsesVarExpr = + VariableExpr.withVariable( + Variable.builder() + .setType( + TypeNode.withReference( + ConcreteReference.builder() + .setClazz(List.class) + .setGenerics(Arrays.asList(method.outputType().reference())) + .build())) + .setName("actualResponses") + .build()); + + Expr getFutureResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(responseObserverVarExpr) + .setMethodName("future") + .build(); + getFutureResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(getFutureResponseExpr) + .setMethodName("get") + .setReturnType(actualResponsesVarExpr.type()) + .build(); + methodExprs.add( + AssignmentExpr.builder() + .setVariableExpr(actualResponsesVarExpr.toBuilder().setIsDecl(true).build()) + .setValueExpr(getFutureResponseExpr) + .build()); + + // Assert the size is equivalent. + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(STATIC_TYPES.get("Assert")) + .setMethodName("assertEquals") + .setArguments( + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1").build()), + MethodInvocationExpr.builder() + .setExprReferenceExpr(actualResponsesVarExpr) + .setMethodName("size") + .setReturnType(TypeNode.INT) + .build()) + .build()); + + // Assert the responses are equivalent. + Expr zeroExpr = + ValueExpr.withValue(PrimitiveValue.builder().setType(TypeNode.INT).setValue("0").build()); + Expr actualResponseExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(actualResponsesVarExpr) + .setMethodName("get") + .setArguments(zeroExpr) + .build(); + + methodExprs.add( + MethodInvocationExpr.builder() + .setStaticReferenceType(STATIC_TYPES.get("Assert")) + .setMethodName("assertEquals") + .setArguments(expectedResponseVarExpr, actualResponseExpr) + .build()); + + String testMethodName = String.format("%sTest", JavaStyle.toLowerCamelCase(method.name())); + return MethodDefinition.builder() + .setAnnotations(Arrays.asList(TEST_ANNOTATION)) + .setScope(ScopeNode.PUBLIC) + .setReturnType(TypeNode.VOID) + .setName(testMethodName) + .setBody( + methodExprs.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList())) + .build(); + } + private static MethodDefinition createRpcExceptionTestMethod( Method method, List methodSignature, @@ -938,11 +1179,11 @@ private static MethodDefinition createRpcExceptionTestMethod( methodBody.add(ExprStatement.withExpr(addExceptionExpr)); if (isStreaming) { methodBody.addAll( - createRpcExceptionTestStreamingStatements( + createStreamingRpcExceptionTestStatements( method, classMemberVarExprs, resourceNames, messageTypes)); } else { methodBody.addAll( - createRpcExceptionTestNonStreamingStatements( + createRpcExceptionTestStatements( method, methodSignature, classMemberVarExprs, resourceNames, messageTypes)); } @@ -956,7 +1197,7 @@ private static MethodDefinition createRpcExceptionTestMethod( .build(); } - private static List createRpcExceptionTestStreamingStatements( + private static List createStreamingRpcExceptionTestStatements( Method method, Map classMemberVarExprs, Map resourceNames, @@ -1118,7 +1359,7 @@ private static List createRpcExceptionTestStreamingStatements( return statements; } - private static List createRpcExceptionTestNonStreamingStatements( + private static List createRpcExceptionTestStatements( Method method, List methodSignature, Map classMemberVarExprs, diff --git a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java index 631fe0ad53..59ec4929e1 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java +++ b/src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java @@ -372,19 +372,16 @@ public void generateServiceClasses() { + " EchoResponse expectedResponse =\n" + " EchoResponse.newBuilder().setContent(\"content951530617\").build();\n" + " mockEcho.addResponse(expectedResponse);\n" - + " String content = \"content951530617\";\n" - + " Status error = Status.newBuilder().build();\n" - + " EchoResponse actualResponse = client.expand(content, error);\n" - + " Assert.assertEquals(expectedResponse, actualResponse);\n" - + " List actualRequests = mockEcho.getRequests();\n" - + " Assert.assertEquals(1, actualRequests.size());\n" - + " ExpandRequest actualRequest = ((ExpandRequest) actualRequests.get(0));\n" - + " Assert.assertEquals(content, actualRequest.getContent());\n" - + " Assert.assertEquals(error, actualRequest.getError());\n" - + " Assert.assertTrue(\n" - + " channelProvider.isHeaderSent(\n" - + " ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),\n" - + " GaxGrpcProperties.getDefaultApiClientHeaderPattern()));\n" + + " ExpandRequest request =\n" + + " " + + " ExpandRequest.newBuilder().setContent(\"content951530617\").setInfo(\"info3237038\").build();\n" + + " MockStreamObserver responseObserver = new MockStreamObserver<>();\n" + + " ServerStreamingCallable callable =" + + " client.expandCallable();\n" + + " callable.serverStreamingCall(request, responseObserver);\n" + + " List actualResponses = responseObserver.future().get();\n" + + " Assert.assertEquals(1, actualResponses.size());\n" + + " Assert.assertEquals(expectedResponse, actualResponses.get(0));\n" + " }\n" + "\n" + " @Test\n" @@ -414,17 +411,24 @@ public void generateServiceClasses() { + " EchoResponse expectedResponse =\n" + " EchoResponse.newBuilder().setContent(\"content951530617\").build();\n" + " mockEcho.addResponse(expectedResponse);\n" - + " String content = \"content951530617\";\n" - + " EchoResponse actualResponse = client.collect(content);\n" - + " Assert.assertEquals(expectedResponse, actualResponse);\n" - + " List actualRequests = mockEcho.getRequests();\n" - + " Assert.assertEquals(1, actualRequests.size());\n" - + " EchoRequest actualRequest = ((EchoRequest) actualRequests.get(0));\n" - + " Assert.assertEquals(content, actualRequest.getContent());\n" - + " Assert.assertTrue(\n" - + " channelProvider.isHeaderSent(\n" - + " ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),\n" - + " GaxGrpcProperties.getDefaultApiClientHeaderPattern()));\n" + + " EchoRequest request =\n" + + " EchoRequest.newBuilder()\n" + + " .setName(FoobarName.ofProjectFoobarName(\"[PROJECT]\"," + + " \"[FOOBAR]\").toString())\n" + + " .setParent(FoobarName.ofProjectFoobarName(\"[PROJECT]\"," + + " \"[FOOBAR]\").toString())\n" + + " .setFoobar(Foobar.newBuilder().build())\n" + + " .build();\n" + + " MockStreamObserver responseObserver = new MockStreamObserver<>();\n" + + " ClientStreamingCallable callable =" + + " client.collectCallable();\n" + + " ApiStreamObserver requestObserver =\n" + + " callable.clientStreamingCall(request, responseObserver);\n" + + " requestObserver.onNext(request);\n" + + " requestObserver.onCompleted();\n" + + " List actualResponses = responseObserver.future().get();\n" + + " Assert.assertEquals(1, actualResponses.size());\n" + + " Assert.assertEquals(expectedResponse, actualResponses.get(0));\n" + " }\n" + "\n" + " @Test\n" @@ -471,21 +475,16 @@ public void generateServiceClasses() { + " \"[FOOBAR]\").toString())\n" + " .setFoobar(Foobar.newBuilder().build())\n" + " .build();\n" - + " EchoResponse actualResponse = client.chat(request);\n" - + " Assert.assertEquals(expectedResponse, actualResponse);\n" - + " List actualRequests = mockEcho.getRequests();\n" - + " Assert.assertEquals(1, actualRequests.size());\n" - + " EchoRequest actualRequest = ((EchoRequest) actualRequests.get(0));\n" - + " Assert.assertEquals(request.getName(), actualRequest.getName());\n" - + " Assert.assertEquals(request.getParent(), actualRequest.getParent());\n" - + " Assert.assertEquals(request.getContent(), actualRequest.getContent());\n" - + " Assert.assertEquals(request.getError(), actualRequest.getError());\n" - + " Assert.assertEquals(request.getSeverity(), actualRequest.getSeverity());\n" - + " Assert.assertEquals(request.getFoobar(), actualRequest.getFoobar());\n" - + " Assert.assertTrue(\n" - + " channelProvider.isHeaderSent(\n" - + " ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),\n" - + " GaxGrpcProperties.getDefaultApiClientHeaderPattern()));\n" + + " MockStreamObserver responseObserver = new MockStreamObserver<>();\n" + + " BidiStreamingCallable callable =" + + " client.chatCallable();\n" + + " ApiStreamObserver requestObserver =\n" + + " callable.bidiStreamingCall(request, responseObserver);\n" + + " requestObserver.onNext(request);\n" + + " requestObserver.onCompleted();\n" + + " List actualResponses = responseObserver.future().get();\n" + + " Assert.assertEquals(1, actualResponses.size());\n" + + " Assert.assertEquals(expectedResponse, actualResponses.get(0));\n" + " }\n" + "\n" + " @Test\n" @@ -524,17 +523,24 @@ public void generateServiceClasses() { + " EchoResponse expectedResponse =\n" + " EchoResponse.newBuilder().setContent(\"content951530617\").build();\n" + " mockEcho.addResponse(expectedResponse);\n" - + " String content = \"content951530617\";\n" - + " EchoResponse actualResponse = client.chatAgain(content);\n" - + " Assert.assertEquals(expectedResponse, actualResponse);\n" - + " List actualRequests = mockEcho.getRequests();\n" - + " Assert.assertEquals(1, actualRequests.size());\n" - + " EchoRequest actualRequest = ((EchoRequest) actualRequests.get(0));\n" - + " Assert.assertEquals(content, actualRequest.getContent());\n" - + " Assert.assertTrue(\n" - + " channelProvider.isHeaderSent(\n" - + " ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),\n" - + " GaxGrpcProperties.getDefaultApiClientHeaderPattern()));\n" + + " EchoRequest request =\n" + + " EchoRequest.newBuilder()\n" + + " .setName(FoobarName.ofProjectFoobarName(\"[PROJECT]\"," + + " \"[FOOBAR]\").toString())\n" + + " .setParent(FoobarName.ofProjectFoobarName(\"[PROJECT]\"," + + " \"[FOOBAR]\").toString())\n" + + " .setFoobar(Foobar.newBuilder().build())\n" + + " .build();\n" + + " MockStreamObserver responseObserver = new MockStreamObserver<>();\n" + + " BidiStreamingCallable callable =" + + " client.chatAgainCallable();\n" + + " ApiStreamObserver requestObserver =\n" + + " callable.bidiStreamingCall(request, responseObserver);\n" + + " requestObserver.onNext(request);\n" + + " requestObserver.onCompleted();\n" + + " List actualResponses = responseObserver.future().get();\n" + + " Assert.assertEquals(1, actualResponses.size());\n" + + " Assert.assertEquals(expectedResponse, actualResponses.get(0));\n" + " }\n" + "\n" + " @Test\n"