diff --git a/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/CoroutineConformanceTests.kt b/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/CoroutineConformanceTests.kt index d1044762..6567c567 100644 --- a/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/CoroutineConformanceTests.kt +++ b/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/CoroutineConformanceTests.kt @@ -42,6 +42,7 @@ import com.microsoft.thrifty.testing.ServerProtocol import com.microsoft.thrifty.testing.ServerTransport import com.microsoft.thrifty.testing.TestServer import com.microsoft.thrifty.transport.FramedTransport +import com.microsoft.thrifty.transport.HttpTransport import com.microsoft.thrifty.transport.SocketTransport import com.microsoft.thrifty.transport.Transport import io.kotest.assertions.fail @@ -73,6 +74,9 @@ class NonblockingCompactCoroutineConformanceTest : CoroutineConformanceTests() @ServerConfig(transport = ServerTransport.NON_BLOCKING, protocol = ServerProtocol.JSON) class NonblockingJsonCoroutineConformanceTest : CoroutineConformanceTests() +@ServerConfig(transport = ServerTransport.HTTP, protocol = ServerProtocol.JSON) +class HttpJsonCoroutineConformanceTest : CoroutineConformanceTests() + /** * A test of auto-generated service code for the standard ThriftTest * service. @@ -103,12 +107,7 @@ abstract class CoroutineConformanceTests { @BeforeAll @JvmStatic fun beforeAll() { - val port = testServer.port() - val transport = SocketTransport.Builder("localhost", port) - .readTimeout(2000) - .build() - - transport.connect() + val transport = getTransportImpl() this.transport = decorateTransport(transport) this.protocol = createProtocol(this.transport) @@ -123,6 +122,18 @@ abstract class CoroutineConformanceTests { }) } + private fun getTransportImpl(): Transport { + return when(testServer.transport) { + ServerTransport.BLOCKING, ServerTransport.NON_BLOCKING -> + return SocketTransport.Builder("localhost", testServer.port()) + .readTimeout(2000) + .build() + .apply { connect() } + + ServerTransport.HTTP -> HttpTransport("http://localhost:${testServer.port()}/test/service") + } + } + /** * When overridden in a derived class, wraps the given transport * in a decorator, e.g. a framed transport. diff --git a/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/KotlinConformanceTest.kt b/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/KotlinConformanceTest.kt index de7808ff..a7eb48ae 100644 --- a/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/KotlinConformanceTest.kt +++ b/thrifty-integration-tests/src/test/kotlin/com/microsoft/thrifty/integration/conformance/KotlinConformanceTest.kt @@ -42,6 +42,7 @@ import com.microsoft.thrifty.testing.ServerProtocol import com.microsoft.thrifty.testing.ServerTransport import com.microsoft.thrifty.testing.TestServer import com.microsoft.thrifty.transport.FramedTransport +import com.microsoft.thrifty.transport.HttpTransport import com.microsoft.thrifty.transport.SocketTransport import com.microsoft.thrifty.transport.Transport import io.kotest.matchers.should @@ -72,6 +73,9 @@ class NonblockingCompactConformanceTest : KotlinConformanceTest() @ServerConfig(transport = ServerTransport.NON_BLOCKING, protocol = ServerProtocol.JSON) class NonblockingJsonConformanceTest : KotlinConformanceTest() +@ServerConfig(transport = ServerTransport.HTTP, protocol = ServerProtocol.JSON) +class HttpJsonConformanceTest : KotlinConformanceTest() + /** * A test of auto-generated service code for the standard ThriftTest * service. @@ -102,12 +106,7 @@ abstract class KotlinConformanceTest { @BeforeAll @JvmStatic fun beforeAll() { - val port = testServer.port() - val transport = SocketTransport.Builder("localhost", port) - .readTimeout(2000) - .build() - - transport.connect() + val transport = getTransportImpl() this.transport = decorateTransport(transport) this.protocol = createProtocol(this.transport) @@ -122,6 +121,18 @@ abstract class KotlinConformanceTest { }) } + private fun getTransportImpl(): Transport { + return when(testServer.transport) { + ServerTransport.BLOCKING, ServerTransport.NON_BLOCKING -> + return SocketTransport.Builder("localhost", testServer.port()) + .readTimeout(2000) + .build() + .apply { connect() } + + ServerTransport.HTTP -> HttpTransport("http://localhost:${testServer.port()}/test/service") + } + } + /** * When overridden in a derived class, wraps the given transport * in a decorator, e.g. a framed transport. diff --git a/thrifty-test-server/build.gradle b/thrifty-test-server/build.gradle index c1cb84d2..dae022fb 100644 --- a/thrifty-test-server/build.gradle +++ b/thrifty-test-server/build.gradle @@ -28,4 +28,5 @@ dependencies { implementation "commons-codec:commons-codec:1.15" implementation "org.apache.httpcomponents:httpclient:4.5.13" implementation "org.slf4j:slf4j-api:2.0.5" + implementation "org.apache.tomcat.embed:tomcat-embed-core:10.1.4" } diff --git a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/HttpServer.java b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/HttpServer.java new file mode 100644 index 00000000..2238a101 --- /dev/null +++ b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/HttpServer.java @@ -0,0 +1,49 @@ +package com.microsoft.thrifty.testing; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.startup.Tomcat; + +import static com.microsoft.thrifty.testing.TestServer.getProtocolFactory; + +public class HttpServer implements TestServerInterface { + private Tomcat tomcat; + + @Override + public void run(ServerProtocol protocol, ServerTransport transport) { + if (transport != ServerTransport.HTTP) { + throw new IllegalArgumentException("only http transport supported"); + } + this.tomcat = new Tomcat(); + tomcat.setBaseDir(System.getProperty("user.dir") + "\\build"); + tomcat.setPort(0); + tomcat.getHost().setAutoDeploy(false); + + String contextPath = "/test"; + StandardContext context = new StandardContext(); + context.setPath(contextPath); + context.addLifecycleListener(new Tomcat.FixContextListener()); + tomcat.getHost().addChild(context); + tomcat.addServlet(contextPath, "testServlet", new TestServlet(getProtocolFactory(protocol))); + context.addServletMappingDecoded("/service", "testServlet"); + try { + tomcat.start(); + } catch (LifecycleException e) { + throw new RuntimeException(e); + } + } + + @Override + public int port() { + return tomcat.getConnector().getLocalPort(); + } + + @Override + public void close() { + try { + tomcat.stop(); + } catch (LifecycleException e) { + throw new RuntimeException(e); + } + } +} diff --git a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/ServerTransport.java b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/ServerTransport.java index 42770901..e14b1d38 100644 --- a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/ServerTransport.java +++ b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/ServerTransport.java @@ -29,5 +29,6 @@ public enum ServerTransport { /** * A framed, non-blocking server socket,i.e. TNonblockingServerTransport. */ - NON_BLOCKING + NON_BLOCKING, + HTTP } diff --git a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServer.java b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServer.java index 246c66ba..01399145 100644 --- a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServer.java +++ b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServer.java @@ -66,6 +66,8 @@ private TestServerInterface getServerImplementation(ServerTransport transport) { case BLOCKING: case NON_BLOCKING: return new SocketBasedServer(); + case HTTP: + return new HttpServer(); default: throw new AssertionError("Invalid transport type: " + transport); } diff --git a/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServlet.java b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServlet.java new file mode 100644 index 00000000..afb49360 --- /dev/null +++ b/thrifty-test-server/src/main/java/com/microsoft/thrifty/testing/TestServlet.java @@ -0,0 +1,51 @@ +/* + * 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 com.microsoft.thrifty.testing; + +import com.microsoft.thrifty.test.gen.ThriftTest; +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.server.TExtensibleServlet; + +@SuppressWarnings("serial") +public class TestServlet extends TExtensibleServlet { + private final TProtocolFactory protocolFactory; + + public TestServlet(TProtocolFactory protocolFactory) { + this.protocolFactory = protocolFactory; + } + + @Override + protected TProtocolFactory getInProtocolFactory() { + return protocolFactory; + } + + @Override + protected TProtocolFactory getOutProtocolFactory() { + return protocolFactory; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + protected TProcessor getProcessor() { + ThriftTestHandler handler = new ThriftTestHandler(System.out); + return new ThriftTest.Processor<>(handler); + } +}