/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.camel.component.grpc; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.support.SynchronizationAdapter; import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class GrpcProducerAsyncTest extends CamelTestSupport { private static final Logger LOG = LoggerFactory.getLogger(GrpcProducerAsyncTest.class); private static final int GRPC_TEST_PORT = AvailablePortFinder.getNextAvailable(); private static final int GRPC_TEST_PING_ID = 1; private static final int GRPC_TEST_PONG_ID01 = 1; private static final int GRPC_TEST_PONG_ID02 = 2; private static final String GRPC_TEST_PING_VALUE = "PING"; private static final String GRPC_TEST_PONG_VALUE = "PONG"; private static Server grpcServer; private Object asyncPongResponse; @BeforeClass public static void startGrpcServer() throws Exception { grpcServer = ServerBuilder.forPort(GRPC_TEST_PORT).addService(new PingPongImpl()).build().start(); LOG.info("gRPC server started on port " + GRPC_TEST_PORT); } @AfterClass public static void stopGrpcServer() throws IOException { if (grpcServer != null) { grpcServer.shutdown(); LOG.info("gRPC server stoped"); } } @Test public void testPingSyncSyncMethodInvocation() throws Exception { LOG.info("gRPC PingSyncSync method test start"); final CountDownLatch latch = new CountDownLatch(1); PingRequest pingRequest = PingRequest.newBuilder().setPingName(GRPC_TEST_PING_VALUE).setPingId(GRPC_TEST_PING_ID).build(); // Testing sync service call with async style invocation template.asyncCallbackSendBody("direct:grpc-sync-sync", pingRequest, new SynchronizationAdapter() { @Override public void onComplete(Exchange exchange) { asyncPongResponse = exchange.getOut().getBody(); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertNotNull(asyncPongResponse); assertTrue(asyncPongResponse instanceof List); @SuppressWarnings("unchecked") List<PongResponse> asyncPongResponseList = (List<PongResponse>)asyncPongResponse; assertEquals(1, asyncPongResponseList.size()); assertEquals(asyncPongResponseList.get(0).getPongId(), GRPC_TEST_PING_ID); assertEquals(asyncPongResponseList.get(0).getPongName(), GRPC_TEST_PING_VALUE + GRPC_TEST_PONG_VALUE); } @Test public void testPingSyncAsyncMethodInvocation() throws Exception { LOG.info("gRPC PingSyncAsync method test start"); final CountDownLatch latch = new CountDownLatch(1); PingRequest pingRequest = PingRequest.newBuilder().setPingName(GRPC_TEST_PING_VALUE).setPingId(GRPC_TEST_PING_ID).build(); // Testing async service call template.asyncCallbackSendBody("direct:grpc-sync-async", pingRequest, new SynchronizationAdapter() { @Override public void onComplete(Exchange exchange) { asyncPongResponse = exchange.getOut().getBody(); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertNotNull(asyncPongResponse); assertTrue(asyncPongResponse instanceof List); @SuppressWarnings("unchecked") List<PongResponse> asyncPongResponseList = (List<PongResponse>)asyncPongResponse; assertEquals(2, asyncPongResponseList.size()); assertEquals(asyncPongResponseList.get(0).getPongId(), GRPC_TEST_PONG_ID01); assertEquals(asyncPongResponseList.get(1).getPongId(), GRPC_TEST_PONG_ID02); assertEquals(asyncPongResponseList.get(0).getPongName(), GRPC_TEST_PING_VALUE + GRPC_TEST_PONG_VALUE); } @Test public void testPingAsyncSyncMethodInvocation() throws Exception { LOG.info("gRPC PingAsyncSync method test start"); final CountDownLatch latch = new CountDownLatch(1); PingRequest pingRequest = PingRequest.newBuilder().setPingName(GRPC_TEST_PING_VALUE).setPingId(GRPC_TEST_PING_ID).build(); // Testing async service call with async style invocation template.asyncCallbackSendBody("direct:grpc-async-sync", pingRequest, new SynchronizationAdapter() { @Override public void onComplete(Exchange exchange) { asyncPongResponse = exchange.getOut().getBody(); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertNotNull(asyncPongResponse); assertTrue(asyncPongResponse instanceof List); @SuppressWarnings("unchecked") List<PongResponse> asyncPongResponseList = (List<PongResponse>)asyncPongResponse; assertEquals(1, asyncPongResponseList.size()); assertEquals(asyncPongResponseList.get(0).getPongId(), GRPC_TEST_PING_ID); assertEquals(asyncPongResponseList.get(0).getPongName(), GRPC_TEST_PING_VALUE + GRPC_TEST_PONG_VALUE); } @Test public void testPingAsyncAsyncMethodInvocation() throws Exception { LOG.info("gRPC PingAsyncAsync method test start"); final CountDownLatch latch = new CountDownLatch(1); PingRequest pingRequest = PingRequest.newBuilder().setPingName(GRPC_TEST_PING_VALUE).setPingId(GRPC_TEST_PING_ID).build(); // Testing async service call with async style invocation template.asyncCallbackSendBody("direct:grpc-async-async", pingRequest, new SynchronizationAdapter() { @Override public void onComplete(Exchange exchange) { asyncPongResponse = exchange.getOut().getBody(); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertNotNull(asyncPongResponse); assertTrue(asyncPongResponse instanceof List); @SuppressWarnings("unchecked") List<PongResponse> asyncPongResponseList = (List<PongResponse>)asyncPongResponse; assertEquals(1, asyncPongResponseList.size()); assertEquals(asyncPongResponseList.get(0).getPongId(), GRPC_TEST_PING_ID); assertEquals(asyncPongResponseList.get(0).getPongName(), GRPC_TEST_PING_VALUE + GRPC_TEST_PONG_VALUE); } @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() { from("direct:grpc-sync-sync").to("grpc://org.apache.camel.component.grpc.PingPong?method=pingSyncSync&host=localhost&port=" + GRPC_TEST_PORT); from("direct:grpc-sync-async").to("grpc://org.apache.camel.component.grpc.PingPong?method=pingSyncAsync&host=localhost&port=" + GRPC_TEST_PORT); from("direct:grpc-async-sync").to("grpc://org.apache.camel.component.grpc.PingPong?method=pingAsyncSync&host=localhost&port=" + GRPC_TEST_PORT); from("direct:grpc-async-async").to("grpc://org.apache.camel.component.grpc.PingPong?method=pingAsyncAsync&host=localhost&port=" + GRPC_TEST_PORT); } }; } /** * Test gRPC PingPong server implementation */ static class PingPongImpl extends PingPongGrpc.PingPongImplBase { @Override public void pingSyncSync(PingRequest request, StreamObserver<PongResponse> responseObserver) { LOG.info("gRPC server received data from PingPong service PingId={} PingName={}", request.getPingId(), request.getPingName()); PongResponse response = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE).setPongId(request.getPingId()).build(); responseObserver.onNext(response); responseObserver.onCompleted(); } @Override public void pingSyncAsync(PingRequest request, StreamObserver<PongResponse> responseObserver) { LOG.info("gRPC server received data from PingAsyncResponse service PingId={} PingName={}", request.getPingId(), request.getPingName()); PongResponse response01 = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE).setPongId(GRPC_TEST_PONG_ID01).build(); PongResponse response02 = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE).setPongId(GRPC_TEST_PONG_ID02).build(); responseObserver.onNext(response01); responseObserver.onNext(response02); responseObserver.onCompleted(); } @Override public StreamObserver<PingRequest> pingAsyncSync(StreamObserver<PongResponse> responseObserver) { @SuppressWarnings({"unchecked", "rawtypes"}) StreamObserver<PingRequest> requestObserver = new StreamObserver<PingRequest>() { @Override public void onNext(PingRequest request) { PongResponse response = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE).setPongId(request.getPingId()).build(); responseObserver.onNext(response); } @Override public void onError(Throwable t) { LOG.info("Error in pingAsyncSync() " + t.getMessage()); } @Override public void onCompleted() { responseObserver.onCompleted(); } }; return requestObserver; } @Override public StreamObserver<PingRequest> pingAsyncAsync(StreamObserver<PongResponse> responseObserver) { @SuppressWarnings({"unchecked", "rawtypes"}) StreamObserver<PingRequest> requestObserver = new StreamObserver<PingRequest>() { @Override public void onNext(PingRequest request) { PongResponse response = PongResponse.newBuilder().setPongName(request.getPingName() + GRPC_TEST_PONG_VALUE).setPongId(request.getPingId()).build(); responseObserver.onNext(response); } @Override public void onError(Throwable t) { LOG.info("Error in pingAsyncAsync() " + t.getMessage()); } @Override public void onCompleted() { responseObserver.onCompleted(); } }; return requestObserver; } } }