Migrate vertx tests to HttpServerTest

This commit is contained in:
Tyler Benson 2019-08-05 08:42:15 -07:00
parent c5ccc67743
commit 668b1059f5
16 changed files with 396 additions and 556 deletions

View File

@ -20,7 +20,7 @@ abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest<AkkaHttp
} }
@Override @Override
boolean hasExceptionBody() { boolean testExceptionBody() {
false false
} }

View File

@ -19,6 +19,12 @@ muzzle {
versions = "[4.0.0.Final,4.1.0.Final)" versions = "[4.0.0.Final,4.1.0.Final)"
assertInverse = true assertInverse = true
} }
pass {
group = "io.vertx"
module = "vertx-core"
versions = "[2.0.0,3.3.0)"
assertInverse = true
}
} }
apply plugin: 'org.unbroken-dome.test-sets' apply plugin: 'org.unbroken-dome.test-sets'

View File

@ -18,6 +18,12 @@ muzzle {
versions = "[4.1.0.Final,)" versions = "[4.1.0.Final,)"
assertInverse = true assertInverse = true
} }
pass {
group = "io.vertx"
module = "vertx-core"
versions = "[3.3.0,)"
assertInverse = true
}
} }
apply plugin: 'org.unbroken-dome.test-sets' apply plugin: 'org.unbroken-dome.test-sets'

View File

@ -1,157 +0,0 @@
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.utils.OkHttpUtils
import datadog.trace.agent.test.utils.PortUtils
import datadog.trace.api.DDSpanTypes
import io.netty.handler.codec.http.HttpResponseStatus
import io.opentracing.tag.Tags
import io.vertx.core.Vertx
import okhttp3.OkHttpClient
import okhttp3.Request
import spock.lang.Shared
class VertxRxServerTest extends AgentTestRunner {
@Shared
OkHttpClient client = OkHttpUtils.client()
@Shared
int port
@Shared
Vertx server
def setupSpec() {
port = PortUtils.randomOpenPort()
server = VertxRxWebTestServer.start(port)
}
def cleanupSpec() {
server.close()
}
def "test server request/response"() {
setup:
def request = new Request.Builder()
.url("http://localhost:$port/proxy")
.header("x-datadog-trace-id", "123")
.header("x-datadog-parent-id", "456")
.get()
.build()
def response = client.newCall(request).execute()
expect:
response.code() == 200
response.body().string() == "Hello World"
and:
assertTraces(2) {
trace(0, 2) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName "GET /test"
childOf(trace(1).get(1))
spanType DDSpanTypes.HTTP_SERVER
errored false
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/test"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
defaultTags(true)
}
}
span(1) {
childOf span(0)
assert span(1).operationName.endsWith('.tracedMethod')
}
}
trace(1, 2) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName "GET /proxy"
traceId "123"
parentId "456"
spanType DDSpanTypes.HTTP_SERVER
errored false
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/proxy"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
defaultTags(true)
}
}
span(1) {
serviceName "unnamed-java-app"
operationName "netty.client.request"
resourceName "GET /test"
childOf(span(0))
spanType DDSpanTypes.HTTP_CLIENT
errored false
tags {
"$Tags.COMPONENT.key" "netty-client"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/test"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
}
def "test #responseCode response handling"() {
setup:
def request = new Request.Builder().url("http://localhost:$port/$path").get().build()
def response = client.newCall(request).execute()
expect:
response.code() == responseCode.code()
and:
assertTraces(1) {
trace(0, 1) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName name
spanType DDSpanTypes.HTTP_SERVER
errored error
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" responseCode.code()
"$Tags.HTTP_URL.key" "http://localhost:$port/$path"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
if (error) {
tag("error", true)
}
defaultTags()
}
}
}
}
where:
responseCode | name | path | error
HttpResponseStatus.OK | "GET /" | "" | false
HttpResponseStatus.NOT_FOUND | "404" | "doesnt-exit" | false
HttpResponseStatus.INTERNAL_SERVER_ERROR | "GET /error" | "error" | true
}
}

View File

@ -1,157 +0,0 @@
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.utils.OkHttpUtils
import datadog.trace.agent.test.utils.PortUtils
import datadog.trace.api.DDSpanTypes
import io.netty.handler.codec.http.HttpResponseStatus
import io.opentracing.tag.Tags
import io.vertx.core.Vertx
import okhttp3.OkHttpClient
import okhttp3.Request
import spock.lang.Shared
class VertxServerTest extends AgentTestRunner {
@Shared
OkHttpClient client = OkHttpUtils.client()
@Shared
int port
@Shared
Vertx server
def setupSpec() {
port = PortUtils.randomOpenPort()
server = VertxWebTestServer.start(port)
}
def cleanupSpec() {
server.close()
}
def "test server request/response"() {
setup:
def request = new Request.Builder()
.url("http://localhost:$port/proxy")
.header("x-datadog-trace-id", "123")
.header("x-datadog-parent-id", "456")
.get()
.build()
def response = client.newCall(request).execute()
expect:
response.code() == 200
response.body().string() == "Hello World"
and:
assertTraces(2) {
trace(0, 2) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName "GET /test"
childOf(trace(1).get(1))
spanType DDSpanTypes.HTTP_SERVER
errored false
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/test"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
defaultTags(true)
}
}
span(1) {
childOf span(0)
assert span(1).operationName.endsWith('.tracedMethod')
}
}
trace(1, 2) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName "GET /proxy"
traceId "123"
parentId "456"
spanType DDSpanTypes.HTTP_SERVER
errored false
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/proxy"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
defaultTags(true)
}
}
span(1) {
serviceName "unnamed-java-app"
operationName "netty.client.request"
resourceName "GET /test"
childOf(span(0))
spanType DDSpanTypes.HTTP_CLIENT
errored false
tags {
"$Tags.COMPONENT.key" "netty-client"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/test"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
defaultTags()
}
}
}
}
}
def "test #responseCode response handling"() {
setup:
def request = new Request.Builder().url("http://localhost:$port/$path").get().build()
def response = client.newCall(request).execute()
expect:
response.code() == responseCode.code()
and:
assertTraces(1) {
trace(0, 1) {
span(0) {
serviceName "unnamed-java-app"
operationName "netty.request"
resourceName name
spanType DDSpanTypes.HTTP_SERVER
errored error
tags {
"$Tags.COMPONENT.key" "netty"
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.HTTP_STATUS.key" responseCode.code()
"$Tags.HTTP_URL.key" "http://localhost:$port/$path"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"
"$Tags.PEER_PORT.key" Integer
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
if (error) {
tag("error", true)
}
defaultTags()
}
}
}
}
where:
responseCode | name | path | error
HttpResponseStatus.OK | "GET /" | "" | false
HttpResponseStatus.NOT_FOUND | "404" | "doesnt-exit" | false
HttpResponseStatus.INTERNAL_SERVER_ERROR | "GET /error" | "error" | true
}
}

View File

@ -1,3 +1,5 @@
package client
import datadog.trace.agent.test.base.HttpClientTest import datadog.trace.agent.test.base.HttpClientTest
import datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator import datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator
import io.vertx.core.Vertx import io.vertx.core.Vertx

View File

@ -0,0 +1,74 @@
package client
import datadog.trace.agent.test.base.HttpClientTest
import datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator
import io.vertx.circuitbreaker.CircuitBreakerOptions
import io.vertx.core.VertxOptions
import io.vertx.core.http.HttpMethod
import io.vertx.ext.web.client.HttpResponse
import io.vertx.reactivex.circuitbreaker.CircuitBreaker
import io.vertx.reactivex.core.Future
import io.vertx.reactivex.core.Vertx
import io.vertx.reactivex.ext.web.client.WebClient
import spock.lang.Shared
import spock.lang.Timeout
import java.util.concurrent.CompletableFuture
@Timeout(10)
class VertxRxCircuitBreakerWebClientTest extends HttpClientTest<NettyHttpClientDecorator> {
@Shared
Vertx vertx = Vertx.vertx(new VertxOptions())
@Shared
WebClient client = WebClient.create(vertx)
@Shared
CircuitBreaker breaker = CircuitBreaker.create("my-circuit-breaker", vertx,
new CircuitBreakerOptions()
.setTimeout(-1) // Disable the timeout otherwise it makes each test take this long.
)
@Override
int doRequest(String method, URI uri, Map<String, String> headers, Closure callback) {
def request = client.request(HttpMethod.valueOf(method), uri.port, uri.host, "$uri")
headers.each { request.putHeader(it.key, it.value) }
Future<HttpResponse> result = breaker.execute { command ->
request.rxSend().doOnSuccess {
command.complete(it)
}.doOnError {
command.fail(it)
}.subscribe()
}
def future = new CompletableFuture<Integer>()
result.setHandler {
callback?.call()
if (it.succeeded()) {
future.complete(it.result().statusCode())
} else {
future.completeExceptionally(it.cause())
}
}
return future.get()
}
@Override
NettyHttpClientDecorator decorator() {
return NettyHttpClientDecorator.DECORATE
}
@Override
String expectedOperationName() {
return "netty.client.request"
}
@Override
boolean testRedirects() {
false
}
@Override
boolean testConnectionFailure() {
false
}
}

View File

@ -1,3 +1,5 @@
package client
import datadog.trace.agent.test.base.HttpClientTest import datadog.trace.agent.test.base.HttpClientTest
import datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator import datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator
import io.vertx.core.VertxOptions import io.vertx.core.VertxOptions

View File

@ -0,0 +1,22 @@
package server;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import datadog.trace.agent.test.base.HttpServerTestAdvice;
import datadog.trace.agent.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NettyServerTestInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.netty.handler.codec.ByteToMessageDecoder"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
named("channelRead"), HttpServerTestAdvice.ServerEntryAdvice.class.getName()));
}
}

View File

@ -0,0 +1,128 @@
package server
import datadog.trace.agent.test.asserts.ListWriterAssert
import datadog.trace.agent.test.base.HttpServerTest
import datadog.trace.instrumentation.netty41.server.NettyHttpServerDecorator
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType
import io.vertx.core.AbstractVerticle
import io.vertx.core.DeploymentOptions
import io.vertx.core.Future
import io.vertx.core.Vertx
import io.vertx.core.VertxOptions
import io.vertx.core.json.JsonObject
import io.vertx.ext.web.Router
import spock.lang.Shared
import java.util.concurrent.CompletableFuture
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS
class VertxHttpServerTest extends HttpServerTest<NettyHttpServerDecorator> {
public static final String CONFIG_HTTP_SERVER_PORT = "http.server.port"
@Shared
Vertx server
@Override
void startServer(int port) {
server = Vertx.vertx(new VertxOptions()
// Useful for debugging:
// .setBlockedThreadCheckInterval(Integer.MAX_VALUE)
.setClusterPort(port))
final CompletableFuture<Void> future = new CompletableFuture<>()
server.deployVerticle(verticle().name,
new DeploymentOptions()
.setConfig(new JsonObject().put(CONFIG_HTTP_SERVER_PORT, port))
.setInstances(3)) { res ->
if (!res.succeeded()) {
throw new RuntimeException("Cannot deploy server Verticle", res.cause())
}
future.complete(null)
}
future.get()
}
protected Class<io.vertx.reactivex.core.AbstractVerticle> verticle() {
return VertxWebTestServer
}
@Override
void stopServer() {
server.close()
}
@Override
NettyHttpServerDecorator decorator() {
return NettyHttpServerDecorator.DECORATE
}
@Override
String expectedOperationName() {
"netty.request"
}
@Override
boolean testExceptionBody() {
false
}
static class VertxWebTestServer extends AbstractVerticle {
@Override
void start(final Future<Void> startFuture) {
final int port = config().getInteger(CONFIG_HTTP_SERVER_PORT)
final Router router = Router.router(vertx)
router.route(SUCCESS.path).handler { ctx ->
controller(SUCCESS) {
ctx.response().setStatusCode(SUCCESS.status).end(SUCCESS.body)
}
}
router.route(REDIRECT.path).handler { ctx ->
controller(REDIRECT) {
ctx.response().setStatusCode(REDIRECT.status).putHeader("location", REDIRECT.body)
}
}
router.route(ERROR.path).handler { ctx ->
controller(ERROR) {
ctx.response().setStatusCode(ERROR.status).end(ERROR.body)
}
}
router.route(EXCEPTION.path).handler { ctx ->
controller(EXCEPTION) {
throw new Exception(EXCEPTION.body)
}
}
vertx.createHttpServer()
.requestHandler { router.accept(it) }
.listen(port) { startFuture.complete() }
}
}
void cleanAndAssertTraces(
final int size,
@ClosureParams(value = SimpleType, options = "datadog.trace.agent.test.asserts.ListWriterAssert")
@DelegatesTo(value = ListWriterAssert, strategy = Closure.DELEGATE_FIRST)
final Closure spec) {
// If this is failing, make sure HttpServerTestAdvice is applied correctly.
TEST_WRITER.waitForTraces(size * 2)
// Netty closes the parent span before the controller returns, so we need to manually reorder it.
TEST_WRITER.each {
def controllerSpan = it.find {
it.operationName == "controller"
}
if (controllerSpan) {
it.remove(controllerSpan)
it.add(controllerSpan)
}
}
super.cleanAndAssertTraces(size, spec)
}
}

View File

@ -0,0 +1,99 @@
package server
import datadog.trace.agent.test.base.HttpServerTest
import io.vertx.circuitbreaker.CircuitBreakerOptions
import io.vertx.reactivex.circuitbreaker.CircuitBreaker
import io.vertx.reactivex.core.AbstractVerticle
import io.vertx.reactivex.core.Future
import io.vertx.reactivex.ext.web.Router
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS
class VertxRxCircuitBreakerHttpServerTest extends VertxHttpServerTest {
@Override
protected Class<AbstractVerticle> verticle() {
return VertxRxCircuitBreakerWebTestServer
}
static class VertxRxCircuitBreakerWebTestServer extends AbstractVerticle {
@Override
void start(final io.vertx.core.Future<Void> startFuture) {
final int port = config().getInteger(CONFIG_HTTP_SERVER_PORT)
final Router router = Router.router(super.@vertx)
final CircuitBreaker breaker =
CircuitBreaker.create(
"my-circuit-breaker",
super.@vertx,
new CircuitBreakerOptions()
.setTimeout(-1) // Disable the timeout otherwise it makes each test take this long.
)
router.route(SUCCESS.path).handler { ctx ->
def result = breaker.execute { future ->
future.complete(SUCCESS)
}
result.setHandler {
if (it.failed()) {
throw it.cause();
}
HttpServerTest.ServerEndpoint endpoint = it.result()
controller(endpoint) {
ctx.response().setStatusCode(endpoint.status).end(endpoint.body)
}
}
}
router.route(REDIRECT.path).handler { ctx ->
def result = breaker.execute { future ->
future.complete(REDIRECT)
}
result.setHandler {
if (it.failed()) {
throw it.cause();
}
HttpServerTest.ServerEndpoint endpoint = it.result()
controller(endpoint) {
ctx.response().setStatusCode(endpoint.status).putHeader("location", endpoint.body)
}
}
}
router.route(ERROR.path).handler { ctx ->
def result = breaker.execute { future ->
future.complete(ERROR)
}
result.setHandler {
if (it.failed()) {
throw it.cause();
}
HttpServerTest.ServerEndpoint endpoint = it.result()
controller(endpoint) {
ctx.response().setStatusCode(endpoint.status).end(endpoint.body)
}
}
}
router.route(EXCEPTION.path).handler { ctx ->
def result = breaker.execute { future ->
future.fail(new Exception(EXCEPTION.body))
}
result.setHandler {
try {
def cause = it.cause()
controller(EXCEPTION) {
throw cause
}
} catch (Exception ex) {
ctx.response().setStatusCode(EXCEPTION.status).end(ex.message)
}
}
}
super.@vertx.createHttpServer()
.requestHandler { router.accept(it) }
.listen(port) { startFuture.complete() }
}
}
}

View File

@ -0,0 +1,53 @@
package server
import io.vertx.core.Future
import io.vertx.reactivex.core.AbstractVerticle
import io.vertx.reactivex.ext.web.Router
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.REDIRECT
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS
class VertxRxHttpServerTest extends VertxHttpServerTest {
@Override
protected Class<AbstractVerticle> verticle() {
return VertxRxWebTestServer
}
static class VertxRxWebTestServer extends AbstractVerticle {
@Override
void start(final Future<Void> startFuture) {
final int port = config().getInteger(CONFIG_HTTP_SERVER_PORT)
final Router router = Router.router(super.@vertx)
router.route(SUCCESS.path).handler { ctx ->
controller(SUCCESS) {
ctx.response().setStatusCode(SUCCESS.status).end(SUCCESS.body)
}
}
router.route(REDIRECT.path).handler { ctx ->
controller(REDIRECT) {
ctx.response().setStatusCode(REDIRECT.status).putHeader("location", REDIRECT.body)
}
}
router.route(ERROR.path).handler { ctx ->
controller(ERROR) {
ctx.response().setStatusCode(ERROR.status).end(ERROR.body)
}
}
router.route(EXCEPTION.path).handler { ctx ->
controller(EXCEPTION) {
throw new Exception(EXCEPTION.body)
}
}
super.@vertx.createHttpServer()
.requestHandler { router.accept(it) }
.listen(port) { startFuture.complete() }
}
}
}

View File

@ -1,116 +0,0 @@
import datadog.trace.api.Trace;
import io.vertx.circuitbreaker.CircuitBreakerOptions;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.reactivex.circuitbreaker.CircuitBreaker;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.buffer.Buffer;
import io.vertx.reactivex.ext.web.Router;
import io.vertx.reactivex.ext.web.RoutingContext;
import io.vertx.reactivex.ext.web.client.WebClient;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class VertxRxWebTestServer extends AbstractVerticle {
public static final String CONFIG_HTTP_SERVER_PORT = "http.server.port";
public static Vertx start(final int port) throws ExecutionException, InterruptedException {
/* This is highly against Vertx ideas, but our tests are synchronous
so we have to make sure server is up and running */
final CompletableFuture<Void> future = new CompletableFuture<>();
final Vertx vertx = Vertx.vertx(new VertxOptions().setClusterPort(port));
vertx.deployVerticle(
VertxRxWebTestServer.class.getName(),
new DeploymentOptions()
.setConfig(new JsonObject().put(CONFIG_HTTP_SERVER_PORT, port))
.setInstances(3),
res -> {
if (!res.succeeded()) {
throw new RuntimeException("Cannot deploy server Verticle", res.cause());
}
future.complete(null);
});
future.get();
return vertx;
}
@Override
public void start(final Future<Void> startFuture) {
// final io.vertx.reactivex.core.Vertx vertx = new io.vertx.reactivex.core.Vertx(this.vertx);
final WebClient client = WebClient.create(vertx);
final int port = config().getInteger(CONFIG_HTTP_SERVER_PORT);
final Router router = Router.router(vertx);
final CircuitBreaker breaker =
CircuitBreaker.create(
"my-circuit-breaker",
vertx,
new CircuitBreakerOptions()
.setMaxFailures(5) // number of failure before opening the circuit
.setTimeout(2000) // consider a failure if the operation does not succeed in time
// .setFallbackOnFailure(true) // do we call the fallback on failure
.setResetTimeout(10000) // time spent in open state before attempting to re-try
);
router
.route("/")
.handler(
routingContext -> {
routingContext.response().putHeader("content-type", "text/html").end("Hello World");
});
router
.route("/error")
.handler(
routingContext -> {
routingContext.response().setStatusCode(500).end();
});
router
.route("/proxy")
.handler(
routingContext -> {
breaker.execute(
ctx -> {
client
.get(port, "localhost", "/test")
.rxSendBuffer(
Optional.ofNullable(routingContext.getBody()).orElse(Buffer.buffer()))
.subscribe(
response -> {
routingContext
.response()
.setStatusCode(response.statusCode())
.end(response.body());
});
});
});
router
.route("/test")
.handler(
routingContext -> {
tracedMethod();
routingContext.next();
})
.blockingHandler(RoutingContext::next)
.handler(
routingContext -> {
routingContext.response().putHeader("content-type", "text/html").end("Hello World");
});
vertx
.createHttpServer()
.requestHandler(router::accept)
.listen(port, h -> startFuture.complete());
}
@Trace
private void tracedMethod() {}
}

View File

@ -1,107 +0,0 @@
import static datadog.trace.agent.test.AgentTestRunner.blockUntilChildSpansFinished;
import datadog.trace.api.Trace;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class VertxWebTestServer extends AbstractVerticle {
public static final String CONFIG_HTTP_SERVER_PORT = "http.server.port";
public static Vertx start(final int port) throws ExecutionException, InterruptedException {
/* This is highly against Vertx ideas, but our tests are synchronous
so we have to make sure server is up and running */
final CompletableFuture<Void> future = new CompletableFuture<>();
final Vertx vertx = Vertx.vertx(new VertxOptions().setClusterPort(port));
vertx.deployVerticle(
VertxWebTestServer.class.getName(),
new DeploymentOptions()
.setConfig(new JsonObject().put(CONFIG_HTTP_SERVER_PORT, port))
.setInstances(3),
res -> {
if (!res.succeeded()) {
throw new RuntimeException("Cannot deploy server Verticle", res.cause());
}
future.complete(null);
});
future.get();
return vertx;
}
@Override
public void start(final Future<Void> startFuture) {
final HttpClient client = vertx.createHttpClient();
final int port = config().getInteger(CONFIG_HTTP_SERVER_PORT);
final Router router = Router.router(vertx);
router
.route("/")
.handler(
routingContext -> {
routingContext.response().putHeader("content-type", "text/html").end("Hello World");
});
router
.route("/error")
.handler(
routingContext -> {
routingContext.response().setStatusCode(500).end();
});
router
.route("/proxy")
.handler(
routingContext -> {
client
.get(
port,
"localhost",
"/test",
response -> {
response.bodyHandler(
buffer -> {
routingContext
.response()
.setStatusCode(response.statusCode())
.end(buffer);
});
blockUntilChildSpansFinished(1);
})
.end(Optional.ofNullable(routingContext.getBody()).orElse(Buffer.buffer()));
});
router
.route("/test")
.handler(
routingContext -> {
tracedMethod();
routingContext.next();
})
.blockingHandler(RoutingContext::next)
.handler(
routingContext -> {
routingContext.response().putHeader("content-type", "text/html").end("Hello World");
});
vertx
.createHttpServer()
.requestHandler(router::accept)
.listen(port, h -> startFuture.complete());
}
@Trace
private void tracedMethod() {}
}

View File

@ -5,21 +5,6 @@ ext {
apply from: "${rootDir}/gradle/java.gradle" apply from: "${rootDir}/gradle/java.gradle"
muzzle {
pass {
group = "io.vertx"
module = "vertx-web"
versions = "[4.1.0.Final,)"
assertInverse = true
}
pass {
group = "io.netty"
module = "netty"
versions = "[4.1.0.Final,)"
assertInverse = true
}
}
apply plugin: 'org.unbroken-dome.test-sets' apply plugin: 'org.unbroken-dome.test-sets'
testSets { testSets {

View File

@ -72,15 +72,15 @@ abstract class HttpServerTest<DECORATOR extends HttpServerDecorator> extends Age
true true
} }
boolean hasExceptionBody() { boolean testExceptionBody() {
true true
} }
public enum ServerEndpoint { public enum ServerEndpoint {
SUCCESS("success", 200, "success"), SUCCESS("success", 200, "success"),
REDIRECT("redirect", 302, null),
ERROR("error", 500, "controller error"), ERROR("error", 500, "controller error"),
EXCEPTION("exception", 500, "controller exception"), EXCEPTION("exception", 500, "controller exception"),
REDIRECT("redirect", 302, null),
NOT_FOUND("notFound", 404, "not found"), NOT_FOUND("notFound", 404, "not found"),
AUTH_REQUIRED("authRequired", 200, null), AUTH_REQUIRED("authRequired", 200, null),
@ -214,7 +214,7 @@ abstract class HttpServerTest<DECORATOR extends HttpServerDecorator> extends Age
expect: expect:
response.code() == EXCEPTION.status response.code() == EXCEPTION.status
if (hasExceptionBody()) { if (testExceptionBody()) {
assert response.body().string() == EXCEPTION.body assert response.body().string() == EXCEPTION.body
} }