package me.dinowernli.grpc.polyglot.integration; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; import com.google.common.base.Charsets; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import me.dinowernli.grpc.polyglot.io.MessageWriter; import me.dinowernli.grpc.polyglot.testing.RecordingTestService; import me.dinowernli.grpc.polyglot.testing.TestServer; import me.dinowernli.grpc.polyglot.testing.TestUtils; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import polyglot.test.TestProto.TestRequest; import polyglot.test.TestProto.TestResponse; import static com.google.common.truth.Truth.assertThat; import static me.dinowernli.grpc.polyglot.testing.TestUtils.makeArgument; /** * An integration test suite which has the Polyglot client talk to a server which records requests. */ public class ClientServerIntegrationTest { private static final String TEST_UNARY_METHOD = "polyglot.test.TestService/TestMethod"; private static final String TEST_STREAM_METHOD = "polyglot.test.TestService/TestMethodStream"; private static final String TEST_CLIENT_STREAM_METHOD = "polyglot.test.TestService/TestMethodClientStream"; private static final String TEST_BIDI_METHOD = "polyglot.test.TestService/TestMethodBidi"; private static final TestRequest REQUEST = TestRequest.newBuilder() .setMessage("i am totally a message") .build(); @Rule public TemporaryFolder tempDirectory = new TemporaryFolder(); private TestServer testServer; private InputStream storedStdin; private Path responseFilePath; private String storedHomeProperty; @Before public void setUp() throws Throwable { storedHomeProperty = System.getProperty("user.home"); System.setProperty("user.home", tempDirectory.getRoot().getAbsolutePath()); responseFilePath = Files.createTempFile("response", "pb.ascii"); storedStdin = System.in; testServer = TestServer.createAndStart(Optional.empty() /* sslContext */); } @After public void tearDown() throws Throwable { System.setProperty("user.home", storedHomeProperty); testServer.blockingShutdown(); System.setIn(storedStdin); Files.delete(responseFilePath); } @Test public void makesRoundTripUnary() throws Throwable { int serverPort = testServer.getGrpcServerPort(); ImmutableList<String> args = ImmutableList.<String>builder() .addAll(makeArgs(serverPort, TestUtils.TESTING_PROTO_ROOT.toString(), TEST_UNARY_METHOD)) .add(makeArgument("output_file_path", responseFilePath.toString())) .build(); setStdinContents(MessageWriter.writeJsonStream(ImmutableList.of(REQUEST))); // Run the full client. me.dinowernli.grpc.polyglot.Main.main(args.toArray(new String[0])); // Make sure we can parse the response from the file. ImmutableList<TestResponse> responses = TestUtils.readResponseFile(responseFilePath); assertThat(responses).hasSize(1); assertThat(responses.get(0)).isEqualTo(TestServer.UNARY_SERVER_RESPONSE); } @Test public void makesRoundTripServerStream() throws Throwable { int serverPort = testServer.getGrpcServerPort(); ImmutableList<String> args = ImmutableList.<String>builder() .addAll(makeArgs(serverPort, TestUtils.TESTING_PROTO_ROOT.toString(), TEST_STREAM_METHOD)) .add(makeArgument("output_file_path", responseFilePath.toString())) .build(); setStdinContents(MessageWriter.writeJsonStream(ImmutableList.of(REQUEST))); // Run the full client. me.dinowernli.grpc.polyglot.Main.main(args.toArray(new String[0])); // Make sure we can parse the response from the file. ImmutableList<TestResponse> responses = TestUtils.readResponseFile(responseFilePath); assertThat(responses).containsExactly(TestServer.STREAMING_SERVER_RESPONSE); } @Test public void makesRoundTripClientStream() throws Throwable { int serverPort = testServer.getGrpcServerPort(); ImmutableList<String> args = ImmutableList.<String>builder() .addAll(makeArgs( serverPort, TestUtils.TESTING_PROTO_ROOT.toString(), TEST_CLIENT_STREAM_METHOD)) .add(makeArgument("output_file_path", responseFilePath.toString())) .build(); setStdinContents(MessageWriter.writeJsonStream(ImmutableList.of(REQUEST, REQUEST, REQUEST))); // Run the full client. me.dinowernli.grpc.polyglot.Main.main(args.toArray(new String[0])); // Make sure we can parse the response from the file. ImmutableList<TestResponse> responses = TestUtils.readResponseFile(responseFilePath); assertThat(responses).containsExactly(TestServer.CLIENT_STREAMING_SERVER_RESPONSE); } @Test public void makesRoundTripBidiStream() throws Throwable { int serverPort = testServer.getGrpcServerPort(); ImmutableList<String> args = ImmutableList.<String>builder() .addAll(makeArgs( serverPort, TestUtils.TESTING_PROTO_ROOT.toString(), TEST_BIDI_METHOD)) .add(makeArgument("output_file_path", responseFilePath.toString())) .build(); setStdinContents(MessageWriter.writeJsonStream(ImmutableList.of(REQUEST, REQUEST, REQUEST))); // Run the full client. me.dinowernli.grpc.polyglot.Main.main(args.toArray(new String[0])); // Make sure we can parse the response from the file. ImmutableList<TestResponse> responses = TestUtils.readResponseFile(responseFilePath); assertThat(responses).containsExactly( TestServer.BIDI_SERVER_RESPONSE, TestServer.BIDI_SERVER_RESPONSE, TestServer.BIDI_SERVER_RESPONSE); } @Test(expected = RuntimeException.class) public void rejectsBadInput() throws Throwable { ImmutableList<String> args = makeArgs( testServer.getGrpcServerPort(), TestUtils.TESTING_PROTO_ROOT.toString(), TEST_UNARY_METHOD); setStdinContents("this is not a valid text proto!"); // Run the full client. me.dinowernli.grpc.polyglot.Main.main(args.toArray(new String[0])); RecordingTestService recordingTestService = testServer.getServiceImpl(); assertThat(recordingTestService.numRequests()).isEqualTo(1); assertThat(recordingTestService.getRequest(0)).isEqualTo(REQUEST); } private static ImmutableList<String> makeArgs(int port, String protoRoot, String method) { return TestUtils.makePolyglotCallArgs( Joiner.on(':').join("localhost", port), protoRoot, method); } private static void setStdinContents(String contents) { System.setIn(new ByteArrayInputStream(contents.getBytes(Charsets.UTF_8))); } }