diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy deleted file mode 100644 index a5e10807fec1..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import spock.lang.Unroll - -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.HEAD -import javax.ws.rs.OPTIONS -import javax.ws.rs.POST -import javax.ws.rs.PUT -import javax.ws.rs.Path - -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassName - -class JaxrsAnnotationsInstrumentationTest extends AgentInstrumentationSpecification { - - @Unroll - def "span named '#paramName' from annotations on class '#className' when is not root span"() { - setup: - runWithHttpServerSpan { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET " + paramName - kind SERVER - hasNoParent() - attributes { - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_ROUTE" paramName - "$ErrorAttributes.ERROR_TYPE" "_OTHER" - } - } - span(1) { - name "${className}.call" - childOf span(0) - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" obj.getClass().getName() - "$CodeIncubatingAttributes.CODE_FUNCTION" "call" - } - } - } - } - - when: "multiple calls to the same method" - runWithHttpServerSpan { - (1..10).each { - obj.call() - } - } - then: "doesn't increase the cache size" - - where: - paramName | obj - "/a" | new Jax() { - @Path("/a") - void call() { - } - } - "/b" | new Jax() { - @GET - @Path("/b") - void call() { - } - } - "/interface/c" | new InterfaceWithPath() { - @POST - @Path("/c") - void call() { - } - } - "/interface" | new InterfaceWithPath() { - @HEAD - void call() { - } - } - "/abstract/d" | new AbstractClassWithPath() { - @POST - @Path("/d") - void call() { - } - } - "/abstract" | new AbstractClassWithPath() { - @PUT - void call() { - } - } - "/child/e" | new ChildClassWithPath() { - @OPTIONS - @Path("/e") - void call() { - } - } - "/child/call" | new ChildClassWithPath() { - @DELETE - void call() { - } - } - "/child/call" | new ChildClassWithPath() - "/child/call" | new JavaInterfaces.ChildClassOnInterface() - "/child/call" | new JavaInterfaces.DefaultChildClassOnInterface() - - className = getClassName(obj.class) - } - - def "no annotations has no effect"() { - setup: - runWithHttpServerSpan { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind SERVER - attributes { - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$ErrorAttributes.ERROR_TYPE" "_OTHER" - } - } - } - } - - where: - obj | _ - new Jax() { - void call() { - } - } | _ - } - - interface Jax { - void call() - } - - @Path("/interface") - interface InterfaceWithPath extends Jax { - @GET - void call() - } - - @Path("/abstract") - static abstract class AbstractClassWithPath implements Jax { - @PUT - abstract void call() - } - - @Path("child") - static class ChildClassWithPath extends AbstractClassWithPath { - @Path("call") - @POST - void call() { - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/JavaInterfaces.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JavaInterfaces.java similarity index 94% rename from instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/JavaInterfaces.java rename to instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JavaInterfaces.java index bcd5e76cc11d..4348ac468539 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/JavaInterfaces.java +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JavaInterfaces.java @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + import javax.ws.rs.GET; import javax.ws.rs.Path; diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRs2AnnotationsInstrumentationTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRs2AnnotationsInstrumentationTest.java new file mode 100644 index 000000000000..35b0706618c6 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRs2AnnotationsInstrumentationTest.java @@ -0,0 +1,174 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassName; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_ROUTE; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JavaInterfaces.Jax; +import io.opentelemetry.semconv.ErrorAttributes; +import java.util.stream.Stream; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.OPTIONS; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class JaxRs2AnnotationsInstrumentationTest { + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static Stream provideArguments() { + return Stream.of( + Arguments.of( + "/a", + new Jax() { + @Path("/a") + @Override + public void call() {} + }), + Arguments.of( + "/b", + new Jax() { + @GET + @Path("/b") + @Override + public void call() {} + }), + Arguments.of( + "/interface/c", + new InterfaceWithPath() { + @POST + @Path("/c") + @Override + public void call() {} + }), + Arguments.of( + "/interface", + new InterfaceWithPath() { + @HEAD + @Override + public void call() {} + }), + Arguments.of( + "/abstract/d", + new AbstractClassWithPath() { + @POST + @Path("/d") + @Override + public void call() {} + }), + Arguments.of( + "/abstract", + new AbstractClassWithPath() { + @PUT + @Override + public void call() {} + }), + Arguments.of( + "/child/e", + new ChildClassWithPath() { + @OPTIONS + @Path("/e") + @Override + public void call() {} + }), + Arguments.of( + "/child/call", + new ChildClassWithPath() { + @DELETE + @Override + public void call() {} + }), + Arguments.of("/child/call", new ChildClassWithPath()), + Arguments.of("/child/call", new JavaInterfaces.ChildClassOnInterface()), + Arguments.of("/child/call", new JavaInterfaces.DefaultChildClassOnInterface())); + } + + @ParameterizedTest + @MethodSource("provideArguments") + void createSpanForAnnotatedMethod(String path, Jax action) { + String className = getClassName(action.getClass()); + testing.runWithHttpServerSpan(action::call); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + path) + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(HTTP_REQUEST_METHOD, "GET"), + equalTo(HTTP_ROUTE, path), + equalTo(ERROR_TYPE, ErrorAttributes.ErrorTypeValues.OTHER)), + span -> + span.hasName(className + ".call") + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(CODE_NAMESPACE, action.getClass().getName()), + equalTo(CODE_FUNCTION, "call")))); + } + + @Test + void notAnnotatedMethod() { + Jax action = + new Jax() { + @Override + public void call() {} + }; + testing.runWithHttpServerSpan(action::call); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(HTTP_REQUEST_METHOD, "GET"), + equalTo(ERROR_TYPE, ErrorAttributes.ErrorTypeValues.OTHER)))); + } + + @Path("/interface") + interface InterfaceWithPath extends Jax { + @GET + @Override + void call(); + } + + @Path("/abstract") + abstract static class AbstractClassWithPath implements Jax { + @PUT + @Override + public abstract void call(); + } + + @Path("child") + static class ChildClassWithPath extends AbstractClassWithPath { + @Path("call") + @POST + @Override + public void call() {} + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy deleted file mode 100644 index 5629374bc870..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import spock.lang.Shared -import spock.lang.Unroll - -import javax.ws.rs.container.ContainerRequestContext -import javax.ws.rs.container.ContainerRequestFilter -import javax.ws.rs.container.PreMatching -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.ext.Provider - -@Unroll -abstract class JaxRsFilterTest extends AbstractJaxRsFilterTest { - - @Shared - SimpleRequestFilter simpleRequestFilter = new SimpleRequestFilter() - - @Shared - PrematchRequestFilter prematchRequestFilter = new PrematchRequestFilter() - - @Override - void setAbortStatus(boolean abortNormal, boolean abortPrematch) { - simpleRequestFilter.abort = abortNormal - prematchRequestFilter.abort = abortPrematch - } - - @Provider - static class SimpleRequestFilter implements ContainerRequestFilter { - boolean abort = false - - @Override - void filter(ContainerRequestContext requestContext) throws IOException { - if (abort) { - requestContext.abortWith( - Response.status(Response.Status.UNAUTHORIZED) - .entity("Aborted") - .type(MediaType.TEXT_PLAIN_TYPE) - .build()) - } - } - } - - @Provider - @PreMatching - static class PrematchRequestFilter implements ContainerRequestFilter { - boolean abort = false - - @Override - void filter(ContainerRequestContext requestContext) throws IOException { - if (abort) { - requestContext.abortWith( - Response.status(Response.Status.UNAUTHORIZED) - .entity("Aborted Prematch") - .type(MediaType.TEXT_PLAIN_TYPE) - .build()) - } - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy deleted file mode 100644 index 97391da68a1e..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.TimeUnit -import test.JaxRsTestResource - -abstract class JaxRsHttpServerTest extends AbstractJaxRsHttpServerTest { - - def setup() { - // reset the barrier to avoid a failing test breaking subsequent tests - JaxRsTestResource.BARRIER.reset() - } - - @Override - void awaitBarrier(int amount, TimeUnit timeUnit) { - JaxRsTestResource.BARRIER.await(amount, timeUnit) - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy deleted file mode 100644 index e817cb56e050..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.webapp.WebAppContext - -import static org.eclipse.jetty.util.resource.Resource.newResource - -abstract class JaxRsJettyHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - WebAppContext webAppContext = new WebAppContext() - webAppContext.setContextPath("/") - // set up test application - webAppContext.setBaseResource(newResource("src/test/webapp")) - - def jettyServer = new Server(port) - jettyServer.connectors.each { - it.setHost('localhost') - } - - jettyServer.setHandler(webAppContext) - jettyServer.start() - - return jettyServer - } - - @Override - void stopServer(Server server) { - server.stop() - server.destroy() - } - - @Override - String getContextPath() { - "/rest-app" - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy deleted file mode 100644 index 92b3ae286d63..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import io.opentelemetry.instrumentation.test.base.HttpServerTest - -import javax.ws.rs.ApplicationPath -import javax.ws.rs.GET -import javax.ws.rs.HeaderParam -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.QueryParam -import javax.ws.rs.container.AsyncResponse -import javax.ws.rs.container.Suspended -import javax.ws.rs.core.Application -import javax.ws.rs.core.Context -import javax.ws.rs.core.Response -import javax.ws.rs.core.UriInfo -import javax.ws.rs.ext.ExceptionMapper -import java.util.concurrent.CompletableFuture -import java.util.concurrent.CompletionStage -import java.util.concurrent.CyclicBarrier - -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS -import static java.util.concurrent.TimeUnit.SECONDS - -@Path("") -class JaxRsTestResource { - @Path("/success") - @GET - String success() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } - - @Path("query") - @GET - String query_param(@QueryParam("some") String param) { - HttpServerTest.controller(QUERY_PARAM) { - "some=$param" - } - } - - @Path("redirect") - @GET - Response redirect(@Context UriInfo uriInfo) { - HttpServerTest.controller(REDIRECT) { - Response.status(Response.Status.FOUND) - .location(uriInfo.relativize(new URI(REDIRECT.body))) - .build() - } - } - - @Path("error-status") - @GET - Response error() { - HttpServerTest.controller(ERROR) { - Response.status(ERROR.status) - .entity(ERROR.body) - .build() - } - } - - @Path("exception") - @GET - Object exception() { - HttpServerTest.controller(EXCEPTION) { - throw new Exception(EXCEPTION.body) - } - } - - @Path("path/{id}/param") - @GET - String path_param(@PathParam("id") int id) { - HttpServerTest.controller(PATH_PARAM) { - id - } - } - - @GET - @Path("captureHeaders") - Response capture_headers(@HeaderParam("X-Test-Request") String header) { - HttpServerTest.controller(CAPTURE_HEADERS) { - Response.status(CAPTURE_HEADERS.status) - .header("X-Test-Response", header) - .entity(CAPTURE_HEADERS.body) - .build() - } - } - - @Path("/child") - @GET - void indexed_child(@Context UriInfo uriInfo, @Suspended AsyncResponse response) { - def parameters = uriInfo.queryParameters - - CompletableFuture.runAsync({ - HttpServerTest.controller(INDEXED_CHILD) { - INDEXED_CHILD.collectSpanAttributes { parameters.getFirst(it) } - response.resume("") - } - }) - } - - static final BARRIER = new CyclicBarrier(2) - - @Path("async") - @GET - void asyncOp(@Suspended AsyncResponse response, @QueryParam("action") String action) { - CompletableFuture.runAsync({ - // await for the test method to verify that there are no spans yet - BARRIER.await(10, SECONDS) - - switch (action) { - case "succeed": - response.resume("success") - break - case "throw": - response.resume(new Exception("failure")) - break - case "cancel": - response.cancel() - break - default: - response.resume(new AssertionError((Object) ("invalid action value: " + action))) - break - } - }) - } - - @Path("async-completion-stage") - @GET - CompletionStage jaxRs21Async(@QueryParam("action") String action) { - def result = new CompletableFuture() - CompletableFuture.runAsync({ - // await for the test method to verify that there are no spans yet - BARRIER.await(10, SECONDS) - - switch (action) { - case "succeed": - result.complete("success") - break - case "throw": - result.completeExceptionally(new Exception("failure")) - break - default: - result.completeExceptionally(new AssertionError((Object) ("invalid action value: " + action))) - break - } - }) - result - } -} - -@Path("test-resource-super") -class JaxRsSuperClassTestResource extends JaxRsSuperClassTestResourceSuper { -} - -class JaxRsSuperClassTestResourceSuper { - @GET - Object call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -class JaxRsInterfaceClassTestResource extends JaxRsInterfaceClassTestResourceSuper implements JaxRsInterface { -} - -@Path("test-resource-interface") -interface JaxRsInterface { - @Path("call") - @GET - Object call() -} - -class JaxRsInterfaceClassTestResourceSuper { - Object call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -@Path("test-sub-resource-locator") -class JaxRsSubResourceLocatorTestResource { - @Path("call") - Object call() { - HttpServerTest.controller(SUCCESS) { - return new SubResource() - } - } -} - -class SubResource { - @Path("sub") - @GET - String call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -class JaxRsTestExceptionMapper implements ExceptionMapper { - @Override - Response toResponse(Exception exception) { - return Response.status(500) - .entity(exception.message) - .build() - } -} - -class JaxRsTestApplication extends Application { - @Override - Set> getClasses() { - def classes = new HashSet() - classes.add(JaxRsTestResource) - classes.add(JaxRsSuperClassTestResource) - classes.add(JaxRsInterfaceClassTestResource) - classes.add(JaxRsSubResourceLocatorTestResource) - classes.add(JaxRsTestExceptionMapper) - return classes - } -} - -@ApplicationPath("/rest-app") -class JaxRsApplicationPathTestApplication extends JaxRsTestApplication { -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsFilterTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsFilterTest.java new file mode 100644 index 000000000000..7013dd219f9d --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsFilterTest.java @@ -0,0 +1,59 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.AbstractJaxRsFilterTest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +public abstract class JaxRsFilterTest extends AbstractJaxRsFilterTest { + + protected final SimpleRequestFilter simpleRequestFilter = new SimpleRequestFilter(); + protected final PrematchRequestFilter prematchRequestFilter = new PrematchRequestFilter(); + + @Override + protected void setAbortStatus(boolean abortNormal, boolean abortPrematch) { + simpleRequestFilter.abort = abortNormal; + prematchRequestFilter.abort = abortPrematch; + } + + @Provider + protected static class SimpleRequestFilter implements ContainerRequestFilter { + boolean abort = false; + + @Override + public void filter(ContainerRequestContext requestContext) { + if (abort) { + requestContext.abortWith( + Response.status(Response.Status.UNAUTHORIZED) + .entity("Aborted") + .type(MediaType.TEXT_PLAIN_TYPE) + .build()); + } + } + } + + @Provider + @PreMatching + protected static class PrematchRequestFilter implements ContainerRequestFilter { + boolean abort = false; + + @Override + public void filter(ContainerRequestContext requestContext) { + if (abort) { + requestContext.abortWith( + Response.status(Response.Status.UNAUTHORIZED) + .entity("Aborted Prematch") + .type(MediaType.TEXT_PLAIN_TYPE) + .build()); + } + } + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsHttpServerTest.java new file mode 100644 index 000000000000..80eadc14a9b6 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsHttpServerTest.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.AbstractJaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestResource; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.BeforeEach; + +public abstract class JaxRsHttpServerTest extends AbstractJaxRsHttpServerTest { + + @BeforeEach + void setup() { + // reset the barrier to avoid a failing test breaking subsequent tests + JaxRsTestResource.BARRIER.reset(); + } + + @Override + protected void awaitBarrier(int amount, TimeUnit timeUnit) + throws BrokenBarrierException, InterruptedException, TimeoutException { + JaxRsTestResource.BARRIER.await(amount, timeUnit); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsJettyHttpServerTest.java new file mode 100644 index 000000000000..e9fdf1d9a21d --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/JaxRsJettyHttpServerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0; + +import static org.eclipse.jetty.util.resource.Resource.newResource; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; + +public abstract class JaxRsJettyHttpServerTest extends JaxRsHttpServerTest { + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setContextPath("/rest-app"); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } + + @Override + protected Server setupServer() throws Exception { + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath("/"); + // set up test application + webAppContext.setBaseResource(newResource("src/test/webapp")); + + Server jettyServer = new Server(port); + jettyServer.setHandler(webAppContext); + jettyServer.start(); + + return jettyServer; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + server.destroy(); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsApplicationPathTestApplication.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsApplicationPathTestApplication.java new file mode 100644 index 000000000000..65726e3c4c1c --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsApplicationPathTestApplication.java @@ -0,0 +1,11 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import javax.ws.rs.ApplicationPath; + +@ApplicationPath("/rest-app") +public class JaxRsApplicationPathTestApplication extends JaxRsTestApplication {} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterface.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterface.java new file mode 100644 index 000000000000..6f551e610a8f --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterface.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("test-resource-interface") +public interface JaxRsInterface { + @Path("call") + @GET + Object call(); +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResource.java new file mode 100644 index 000000000000..df1cac6ac346 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResource.java @@ -0,0 +1,9 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +public class JaxRsInterfaceClassTestResource extends JaxRsInterfaceClassTestResourceSuper + implements JaxRsInterface {} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResourceSuper.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResourceSuper.java new file mode 100644 index 000000000000..ad17903d0af1 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsInterfaceClassTestResourceSuper.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +public class JaxRsInterfaceClassTestResourceSuper { + public Object call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSubResourceLocatorTestResource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSubResourceLocatorTestResource.java new file mode 100644 index 000000000000..1e78df63f3b9 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSubResourceLocatorTestResource.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import javax.ws.rs.Path; + +@Path("test-sub-resource-locator") +public class JaxRsSubResourceLocatorTestResource { + @Path("call") + public Object call() { + return controller(SUCCESS, SubResource::new); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResource.java new file mode 100644 index 000000000000..52cbfc5a283e --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResource.java @@ -0,0 +1,11 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import javax.ws.rs.Path; + +@Path("test-resource-super") +public class JaxRsSuperClassTestResource extends JaxRsSuperClassTestResourceSuper {} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResourceSuper.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResourceSuper.java new file mode 100644 index 000000000000..ed915b319df6 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsSuperClassTestResourceSuper.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import javax.ws.rs.GET; + +public class JaxRsSuperClassTestResourceSuper { + @GET + public Object call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestApplication.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestApplication.java new file mode 100644 index 000000000000..5c5d40aee276 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestApplication.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import java.util.HashSet; +import java.util.Set; +import javax.ws.rs.core.Application; + +public class JaxRsTestApplication extends Application { + @Override + public Set> getClasses() { + Set> classes = new HashSet<>(); + classes.add(JaxRsTestResource.class); + classes.add(JaxRsSuperClassTestResource.class); + classes.add(JaxRsInterfaceClassTestResource.class); + classes.add(JaxRsSubResourceLocatorTestResource.class); + classes.add(JaxRsTestExceptionMapper.class); + return classes; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestExceptionMapper.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestExceptionMapper.java new file mode 100644 index 000000000000..9de3ab95780e --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestExceptionMapper.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +public class JaxRsTestExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(Exception exception) { + return Response.status(500).entity(exception.getMessage()).build(); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestResource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestResource.java new file mode 100644 index 000000000000..7424a5f41237 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/JaxRsTestResource.java @@ -0,0 +1,174 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CyclicBarrier; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.container.AsyncResponse; +import javax.ws.rs.container.Suspended; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +@SuppressWarnings("IdentifierName") +@Path("") +public class JaxRsTestResource { + @Path("/success") + @GET + public String success() { + return controller(SUCCESS, SUCCESS::getBody); + } + + @Path("query") + @GET + public String query_param(@QueryParam("some") String param) { + return controller(QUERY_PARAM, () -> "some=" + param); + } + + @Path("redirect") + @GET + public Response redirect(@Context UriInfo uriInfo) throws URISyntaxException { + return controller( + SUCCESS, + () -> + Response.status(Response.Status.FOUND) + .location(uriInfo.relativize(new URI(REDIRECT.getBody()))) + .build()); + } + + @Path("error-status") + @GET + public Response error() { + return controller( + SUCCESS, () -> Response.status(ERROR.getStatus()).entity(ERROR.getBody()).build()); + } + + @Path("exception") + @GET + public Object exception() { + return controller( + SUCCESS, + () -> { + throw new IllegalStateException(EXCEPTION.getBody()); + }); + } + + @Path("path/{id}/param") + @GET + public String path_param(@PathParam("id") int id) { + return controller(PATH_PARAM, () -> String.valueOf(id)); + } + + @GET + @Path("captureHeaders") + public Response capture_headers(@HeaderParam("X-Test-Request") String header) { + return controller( + CAPTURE_HEADERS, + () -> + Response.status(CAPTURE_HEADERS.getStatus()) + .header("X-Test-Response", header) + .entity(CAPTURE_HEADERS.getBody()) + .build()); + } + + @Path("/child") + @GET + public void indexed_child(@Context UriInfo uriInfo, @Suspended AsyncResponse response) { + MultivaluedMap parameters = uriInfo.getQueryParameters(); + + CompletableFuture.runAsync( + () -> + controller( + INDEXED_CHILD, + () -> { + INDEXED_CHILD.collectSpanAttributes(parameters::getFirst); + response.resume(""); + })); + } + + public static final CyclicBarrier BARRIER = new CyclicBarrier(2); + + @Path("async") + @GET + public void asyncOp(@Suspended AsyncResponse response, @QueryParam("action") String action) { + CompletableFuture.runAsync( + () -> { + // await for the test method to verify that there are no spans yet + try { + BARRIER.await(10, SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception exception) { + throw new IllegalStateException(exception); + } + + switch (action) { + case "succeed": + response.resume("success"); + break; + case "throw": + response.resume(new IllegalStateException("failure")); + break; + case "cancel": + response.cancel(); + break; + default: + response.resume(new AssertionError("invalid action value: " + action)); + break; + } + }); + } + + @Path("async-completion-stage") + @GET + public CompletionStage jaxRs21Async(@QueryParam("action") String action) { + CompletableFuture result = new CompletableFuture<>(); + CompletableFuture.runAsync( + () -> { + // await for the test method to verify that there are no spans yet + try { + BARRIER.await(10, SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception exception) { + throw new IllegalStateException(exception); + } + + switch (action) { + case "succeed": + result.complete("success"); + break; + case "throw": + result.completeExceptionally(new IllegalStateException("failure")); + break; + default: + result.completeExceptionally(new AssertionError("invalid action value: " + action)); + break; + } + }); + return result; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/Resource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/Resource.java similarity index 93% rename from instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/Resource.java rename to instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/Resource.java index d962f172ca63..38dceb0991c2 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/Resource.java +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/Resource.java @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -// Originally had this as a groovy class but was getting some weird errors. @Path("/ignored") public interface Resource { @Path("ignored") diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/SubResource.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/SubResource.java new file mode 100644 index 000000000000..0fb761b41935 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v2_0/test/SubResource.java @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v2_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +public class SubResource { + @Path("sub") + @GET + public String call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfFilterTest.groovy deleted file mode 100644 index 59e943a3dd6b..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfFilterTest.groovy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import org.apache.cxf.endpoint.Server -import org.apache.cxf.jaxrs.JAXRSServerFactoryBean - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class CxfFilterTest extends JaxRsFilterTest implements HttpServerTestTrait { - - def setupSpec() { - setupServer() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - boolean testAbortPrematch() { - false - } - - @Override - boolean runsOnServer() { - true - } - - @Override - Server startServer(int port) { - JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean() - serverFactory.setProviders([simpleRequestFilter, prematchRequestFilter]) - serverFactory.setResourceClasses([Test1, Test2, Test3]) - serverFactory.setAddress(buildAddress().toString()) - - def server = serverFactory.create() - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - def makeRequest(String path) { - AggregatedHttpResponse response = client.post(address.resolve(path).toString(), "").aggregate().join() - - return [response.contentUtf8(), response.status().code()] - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfHttpServerTest.groovy deleted file mode 100644 index 534816ffecdd..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfHttpServerTest.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.apache.cxf.endpoint.Server -import org.apache.cxf.jaxrs.JAXRSServerFactoryBean -import test.JaxRsTestApplication - -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.ext.ExceptionMapper - -class CxfHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean() - def application = new JaxRsTestApplication() - serverFactory.setApplication(application) - serverFactory.setResourceClasses(new ArrayList>(application.getClasses())) - serverFactory.setProvider(new ExceptionMapper() { - @Override - Response toResponse(Exception exception) { - return Response.status(500) - .type(MediaType.TEXT_PLAIN_TYPE) - .entity(exception.getMessage()) - .build() - } - }) - serverFactory.setAddress(buildAddress().toString()) - - def server = serverFactory.create() - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - Boolean.getBoolean("testLatestDeps") ? 500 : 405 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfJettyHttpServerTest.groovy deleted file mode 100644 index 7bf37d74f381..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/groovy/CxfJettyHttpServerTest.groovy +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class CxfJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - Boolean.getBoolean("testLatestDeps") ? 500 : 405 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfFilterTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfFilterTest.java new file mode 100644 index 000000000000..c06d900d9a2b --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfFilterTest.java @@ -0,0 +1,75 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import static java.util.Arrays.asList; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import org.apache.cxf.endpoint.Server; +import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class CxfFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Server setupServer() { + JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean(); + serverFactory.setProviders(asList(simpleRequestFilter, prematchRequestFilter)); + serverFactory.setResourceClasses( + asList(Resource.Test1.class, Resource.Test2.class, Resource.Test3.class)); + serverFactory.setAddress(buildAddress().toString()); + + Server server = serverFactory.create(); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server server) { + server.stop(); + } + + @Override + protected String getContextPath() { + return ""; + } + + @Override + protected TestResponse makeRequest(String url) { + AggregatedHttpResponse response = + client.post(address.resolve(url).toString(), "").aggregate().join(); + return new TestResponse(response.contentUtf8(), response.status().code()); + } + + @Override + protected boolean testAbortPrematch() { + return false; + } + + @Override + protected boolean runsOnServer() { + return true; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfHttpServerTest.java new file mode 100644 index 000000000000..735751feeaa6 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfHttpServerTest.java @@ -0,0 +1,58 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import java.util.ArrayList; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import org.apache.cxf.endpoint.Server; +import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; +import org.junit.jupiter.api.extension.RegisterExtension; + +class CxfHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected Server setupServer() { + JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean(); + JaxRsTestApplication application = new JaxRsTestApplication(); + serverFactory.setApplication(application); + serverFactory.setResourceClasses(new ArrayList<>(application.getClasses())); + serverFactory.setProvider( + (ExceptionMapper) + exception -> + Response.status(500) + .type(MediaType.TEXT_PLAIN_TYPE) + .entity(exception.getMessage()) + .build()); + + serverFactory.setAddress(buildAddress().toString()); + + Server server = serverFactory.create(); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server httpServer) { + httpServer.stop(); + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfJettyHttpServerTest.java new file mode 100644 index 000000000000..3581b2774bcc --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CxfJettyHttpServerTest.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class CxfJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod( + Boolean.getBoolean("testLatestDeps") ? 500 : 405); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/webapp/WEB-INF/web.xml index de8d09a8c446..581a18d084b8 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-cxf-3.2/javaagent/src/test/webapp/WEB-INF/web.xml @@ -9,7 +9,7 @@ org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet javax.ws.rs.Application - test.JaxRsApplicationPathTestApplication + io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsApplicationPathTestApplication true @@ -18,4 +18,4 @@ CXFNonSpringJaxrsServlet /rest-app/* - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyFilterTest.groovy deleted file mode 100644 index a9486b38bc9e..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyFilterTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import javax.ws.rs.core.Application -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.servlet.ServletHolder -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class JerseyFilterTest extends JaxRsFilterTest implements HttpServerTestTrait { - - def setupSpec() { - setupServer() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - Server startServer(int port) { - def servlet = new ServletContainer(ResourceConfig.forApplication(new TestApplication())) - - def handler = new ServletContextHandler(ServletContextHandler.SESSIONS) - handler.setContextPath("/") - handler.addServlet(new ServletHolder(servlet), "/*") - - def server = new Server(port) - server.setHandler(handler) - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - boolean runsOnServer() { - true - } - - @Override - String defaultServerRoute() { - "/*" - } - - @Override - def makeRequest(String path) { - AggregatedHttpResponse response = client.post(address.resolve(path).toString(), "").aggregate().join() - - return [response.contentUtf8(), response.status().code()] - } - - class TestApplication extends Application { - @Override - Set> getClasses() { - def classes = new HashSet() - classes.add(Test1) - classes.add(Test2) - classes.add(Test3) - return classes - } - - @Override - Set getSingletons() { - def singletons = new HashSet() - singletons.add(simpleRequestFilter) - singletons.add(prematchRequestFilter) - return singletons - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy deleted file mode 100644 index 05d37cd00ef2..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.servlet.ServletHolder -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer -import test.JaxRsTestApplication - -class JerseyHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - def servlet = new ServletContainer(ResourceConfig.forApplicationClass(JaxRsTestApplication)) - - def handler = new ServletContextHandler(ServletContextHandler.SESSIONS) - handler.setContextPath("/") - handler.addServlet(new ServletHolder(servlet), "/*") - - def server = new Server(port) - server.setHandler(handler) - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - boolean asyncCancelHasSendError() { - true - } - - @Override - boolean testInterfaceMethodWithPath() { - // disables a test that jersey deems invalid - false - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy deleted file mode 100644 index 97c4c1c28642..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class JerseyJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - @Override - boolean asyncCancelHasSendError() { - true - } - - @Override - boolean testInterfaceMethodWithPath() { - // disables a test that jersey deems invalid - false - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyStartupListener.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyStartupListener.groovy deleted file mode 100644 index 79c717c1dff2..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/groovy/JerseyStartupListener.groovy +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer -import test.JaxRsApplicationPathTestApplication - -import javax.servlet.ServletContextEvent -import javax.servlet.ServletContextListener - -// ServletContainerInitializer isn't automatically called due to the way this test is set up -// so we call it ourself -class JerseyStartupListener implements ServletContextListener { - @Override - void contextInitialized(ServletContextEvent servletContextEvent) { - new JerseyServletContainerInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication), - servletContextEvent.getServletContext()) - } - - @Override - void contextDestroyed(ServletContextEvent servletContextEvent) { - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyFilterTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyFilterTest.java new file mode 100644 index 000000000000..90814a9db7a3 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyFilterTest.java @@ -0,0 +1,100 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import java.util.HashSet; +import java.util.Set; +import javax.servlet.Servlet; +import javax.ws.rs.core.Application; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Server setupServer() throws Exception { + Servlet servlet = new ServletContainer(ResourceConfig.forApplication(new TestApplication())); + + ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); + handler.setContextPath("/"); + handler.addServlet(new ServletHolder(servlet), "/*"); + + Server server = new Server(port); + server.setHandler(handler); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + } + + @Override + protected String getContextPath() { + return "/*"; + } + + @Override + protected boolean runsOnServer() { + return true; + } + + @Override + protected String defaultServerRoute() { + return "/*"; + } + + @Override + protected TestResponse makeRequest(String url) { + AggregatedHttpResponse response = + client.post(address.resolve(url).toString(), "").aggregate().join(); + return new TestResponse(response.contentUtf8(), response.status().code()); + } + + class TestApplication extends Application { + @Override + public Set> getClasses() { + Set> classes = new HashSet<>(); + classes.add(Resource.Test1.class); + classes.add(Resource.Test2.class); + classes.add(Resource.Test3.class); + return classes; + } + + @Override + public Set getSingletons() { + Set singletons = new HashSet<>(); + singletons.add(simpleRequestFilter); + singletons.add(prematchRequestFilter); + return singletons; + } + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyHttpServerTest.java new file mode 100644 index 000000000000..00c5fe75a4b6 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyHttpServerTest.java @@ -0,0 +1,71 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import javax.servlet.Servlet; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected Server setupServer() throws Exception { + Servlet servlet = + new ServletContainer(ResourceConfig.forApplicationClass(JaxRsTestApplication.class)); + + ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); + handler.setContextPath("/"); + handler.addServlet(new ServletHolder(servlet), "/*"); + + Server server = new Server(port); + server.setHandler(handler); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + } + + @Override + protected boolean asyncCancelHasSendError() { + return true; + } + + @Override + protected boolean testInterfaceMethodWithPath() { + // disables a test that jersey deems invalid + return false; + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyJettyHttpServerTest.java new file mode 100644 index 000000000000..12ff37e61417 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyJettyHttpServerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } + + @Override + protected boolean asyncCancelHasSendError() { + return true; + } + + @Override + protected boolean testInterfaceMethodWithPath() { + // disables a test that jersey deems invalid + return false; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyStartupListener.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyStartupListener.java new file mode 100644 index 000000000000..2a1180e4d3eb --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyStartupListener.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsApplicationPathTestApplication; +import java.util.Collections; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer; + +// ServletContainerInitializer isn't automatically called due to the way this test is set up, +// so we call it ourselves +public class JerseyStartupListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + try { + new JerseyServletContainerInitializer() + .onStartup( + Collections.singleton(JaxRsApplicationPathTestApplication.class), + servletContextEvent.getServletContext()); + } catch (ServletException exception) { + throw new IllegalStateException(exception); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) {} +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/webapp/WEB-INF/web.xml index 5b492283ea2f..94fb17f33718 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/javaagent/src/test/webapp/WEB-INF/web.xml @@ -5,6 +5,6 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> - JerseyStartupListener + io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JerseyStartupListener - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy deleted file mode 100644 index 5661f8120cb9..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.jboss.resteasy.mock.MockDispatcherFactory -import org.jboss.resteasy.mock.MockHttpRequest -import org.jboss.resteasy.mock.MockHttpResponse -import spock.lang.Shared - -import javax.ws.rs.core.MediaType - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class ResteasyFilterTest extends JaxRsFilterTest { - @Shared - def dispatcher - - def setupSpec() { - dispatcher = MockDispatcherFactory.createDispatcher() - def registry = dispatcher.getRegistry() - registry.addSingletonResource(new Test1()) - registry.addSingletonResource(new Test2()) - registry.addSingletonResource(new Test3()) - - dispatcher.getProviderFactory().register(simpleRequestFilter) - dispatcher.getProviderFactory().register(prematchRequestFilter) - } - - @Override - def makeRequest(String url) { - MockHttpRequest request = MockHttpRequest.post(url) - request.contentType(MediaType.TEXT_PLAIN_TYPE) - request.content(new byte[0]) - - MockHttpResponse response = new MockHttpResponse() - dispatcher.invoke(request, response) - - return [response.contentAsString, response.status] - } - -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy deleted file mode 100644 index 94835308b6bb..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import io.undertow.Undertow -import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer -import test.JaxRsTestApplication - -class ResteasyHttpServerTest extends JaxRsHttpServerTest { - - @Override - String getContextPath() { - "/resteasy-context" - } - - @Override - UndertowJaxrsServer startServer(int port) { - def server = new UndertowJaxrsServer() - server.deploy(JaxRsTestApplication, getContextPath()) - server.start(Undertow.builder() - .addHttpListener(port, "localhost")) - return server - } - - @Override - void stopServer(UndertowJaxrsServer server) { - server.stop() - } - - // resteasy 3.0.x does not support JAX-RS 2.1 - @Override - boolean shouldTestCompletableStageAsync() { - false - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy deleted file mode 100644 index 4691531a7292..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - // resteasy 3.0.x does not support JAX-RS 2.1 - boolean shouldTestCompletableStageAsync() { - false - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy deleted file mode 100644 index 89001e5a5157..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer -import test.JaxRsApplicationPathTestApplication - -import javax.servlet.ServletContextEvent -import javax.servlet.ServletContextListener - -// ServletContainerInitializer isn't automatically called due to the way this test is set up -// so we call it ourself -class ResteasyStartupListener implements ServletContextListener { - @Override - void contextInitialized(ServletContextEvent servletContextEvent) { - new ResteasyServletInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication), - servletContextEvent.getServletContext()) - } - - @Override - void contextDestroyed(ServletContextEvent servletContextEvent) { - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java new file mode 100644 index 000000000000..c9099b15e281 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java @@ -0,0 +1,71 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import javax.ws.rs.core.MediaType; +import org.jboss.resteasy.core.Dispatcher; +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.mock.MockHttpRequest; +import org.jboss.resteasy.mock.MockHttpResponse; +import org.jboss.resteasy.spi.Registry; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + private Dispatcher dispatcher; + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Void setupServer() { + dispatcher = MockDispatcherFactory.createDispatcher(); + Registry registry = dispatcher.getRegistry(); + registry.addSingletonResource(new Resource.Test1()); + registry.addSingletonResource(new Resource.Test2()); + registry.addSingletonResource(new Resource.Test3()); + + dispatcher.getProviderFactory().register(simpleRequestFilter); + dispatcher.getProviderFactory().register(prematchRequestFilter); + + return null; + } + + @Override + protected void stopServer(Void server) {} + + @Override + protected String getContextPath() { + return ""; + } + + @Override + protected TestResponse makeRequest(String url) throws Exception { + MockHttpRequest request = MockHttpRequest.post(url); + request.contentType(MediaType.TEXT_PLAIN_TYPE); + request.content(new byte[0]); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + + return new TestResponse(response.getContentAsString(), response.getStatus()); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java new file mode 100644 index 000000000000..98ff16c8b83e --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java @@ -0,0 +1,56 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import io.undertow.Undertow; +import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected UndertowJaxrsServer setupServer() { + UndertowJaxrsServer server = new UndertowJaxrsServer(); + server.deploy(JaxRsTestApplication.class, getContextPath()); + server.start(Undertow.builder().addHttpListener(port, "localhost")); + + return server; + } + + @Override + protected void stopServer(UndertowJaxrsServer server) { + server.stop(); + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setContextPath("/resteasy-context"); + options.setResponseCodeOnNonStandardHttpMethod(500); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } + + // resteasy 3.0.x does not support JAX-RS 2.1 + @Override + protected boolean shouldTestCompletableStageAsync() { + return false; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java new file mode 100644 index 000000000000..86da019629b7 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } + + // resteasy 3.0.x does not support JAX-RS 2.1 + @Override + protected boolean shouldTestCompletableStageAsync() { + return false; + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java new file mode 100644 index 000000000000..d7bea7a1f6b5 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsApplicationPathTestApplication; +import java.util.Collections; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer; + +// ServletContainerInitializer isn't automatically called due to the way this test is set up, +// so we call it ourselves +public class ResteasyStartupListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + try { + new ResteasyServletInitializer() + .onStartup( + Collections.singleton(JaxRsApplicationPathTestApplication.class), + servletContextEvent.getServletContext()); + } catch (ServletException exception) { + throw new IllegalStateException(exception); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) {} +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/webapp/WEB-INF/web.xml index 1da5664333a7..d0b20e81dbab 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/javaagent/src/test/webapp/WEB-INF/web.xml @@ -5,6 +5,6 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> - ResteasyStartupListener + io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.ResteasyStartupListener - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyFilterTest.groovy deleted file mode 100644 index 5661f8120cb9..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyFilterTest.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.jboss.resteasy.mock.MockDispatcherFactory -import org.jboss.resteasy.mock.MockHttpRequest -import org.jboss.resteasy.mock.MockHttpResponse -import spock.lang.Shared - -import javax.ws.rs.core.MediaType - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class ResteasyFilterTest extends JaxRsFilterTest { - @Shared - def dispatcher - - def setupSpec() { - dispatcher = MockDispatcherFactory.createDispatcher() - def registry = dispatcher.getRegistry() - registry.addSingletonResource(new Test1()) - registry.addSingletonResource(new Test2()) - registry.addSingletonResource(new Test3()) - - dispatcher.getProviderFactory().register(simpleRequestFilter) - dispatcher.getProviderFactory().register(prematchRequestFilter) - } - - @Override - def makeRequest(String url) { - MockHttpRequest request = MockHttpRequest.post(url) - request.contentType(MediaType.TEXT_PLAIN_TYPE) - request.content(new byte[0]) - - MockHttpResponse response = new MockHttpResponse() - dispatcher.invoke(request, response) - - return [response.contentAsString, response.status] - } - -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy deleted file mode 100644 index 113b2baab4cf..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import io.undertow.Undertow -import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer -import test.JaxRsTestApplication - -class ResteasyHttpServerTest extends JaxRsHttpServerTest { - - @Override - String getContextPath() { - "/resteasy-context" - } - - @Override - UndertowJaxrsServer startServer(int port) { - def server = new UndertowJaxrsServer() - server.deploy(JaxRsTestApplication, getContextPath()) - server.start(Undertow.builder() - .addHttpListener(port, "localhost")) - return server - } - - @Override - void stopServer(UndertowJaxrsServer server) { - server.stop() - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy deleted file mode 100644 index 8d92d379711a..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyStartupListener.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyStartupListener.groovy deleted file mode 100644 index 89001e5a5157..000000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/groovy/ResteasyStartupListener.groovy +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer -import test.JaxRsApplicationPathTestApplication - -import javax.servlet.ServletContextEvent -import javax.servlet.ServletContextListener - -// ServletContainerInitializer isn't automatically called due to the way this test is set up -// so we call it ourself -class ResteasyStartupListener implements ServletContextListener { - @Override - void contextInitialized(ServletContextEvent servletContextEvent) { - new ResteasyServletInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication), - servletContextEvent.getServletContext()) - } - - @Override - void contextDestroyed(ServletContextEvent servletContextEvent) { - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java new file mode 100644 index 000000000000..f63609deb5f8 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyFilterTest.java @@ -0,0 +1,73 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import javax.ws.rs.core.MediaType; +import org.jboss.resteasy.core.SynchronousDispatcher; +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.mock.MockHttpRequest; +import org.jboss.resteasy.mock.MockHttpResponse; +import org.jboss.resteasy.spi.Registry; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + private SynchronousDispatcher dispatcher; + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Void setupServer() { + // using implementation class SynchronousDispatcher instead of the Dispatcher interface because + // the interface moves to a different package for the latest dep tests + dispatcher = (SynchronousDispatcher) MockDispatcherFactory.createDispatcher(); + Registry registry = dispatcher.getRegistry(); + registry.addSingletonResource(new Resource.Test1()); + registry.addSingletonResource(new Resource.Test2()); + registry.addSingletonResource(new Resource.Test3()); + + dispatcher.getProviderFactory().register(simpleRequestFilter); + dispatcher.getProviderFactory().register(prematchRequestFilter); + + return null; + } + + @Override + protected void stopServer(Void server) {} + + @Override + protected String getContextPath() { + return ""; + } + + @Override + protected TestResponse makeRequest(String url) throws Exception { + MockHttpRequest request = MockHttpRequest.post(url); + request.contentType(MediaType.TEXT_PLAIN_TYPE); + request.content(new byte[0]); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + + return new TestResponse(response.getContentAsString(), response.getStatus()); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java new file mode 100644 index 000000000000..4ed601b35f72 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyHttpServerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import io.undertow.Undertow; +import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected UndertowJaxrsServer setupServer() { + UndertowJaxrsServer server = new UndertowJaxrsServer(); + server.deploy(JaxRsTestApplication.class, getContextPath()); + server.start(Undertow.builder().addHttpListener(port, "localhost")); + + return server; + } + + @Override + protected void stopServer(UndertowJaxrsServer server) { + server.stop(); + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setContextPath("/resteasy-context"); + options.setResponseCodeOnNonStandardHttpMethod(500); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java new file mode 100644 index 000000000000..bff66faf6589 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyJettyHttpServerTest.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java new file mode 100644 index 000000000000..d7bea7a1f6b5 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ResteasyStartupListener.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; + +import io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsApplicationPathTestApplication; +import java.util.Collections; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer; + +// ServletContainerInitializer isn't automatically called due to the way this test is set up, +// so we call it ourselves +public class ResteasyStartupListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + try { + new ResteasyServletInitializer() + .onStartup( + Collections.singleton(JaxRsApplicationPathTestApplication.class), + servletContextEvent.getServletContext()); + } catch (ServletException exception) { + throw new IllegalStateException(exception); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) {} +} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/webapp/WEB-INF/web.xml index 1da5664333a7..d0b20e81dbab 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/javaagent/src/test/webapp/WEB-INF/web.xml @@ -5,6 +5,6 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> - ResteasyStartupListener + io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.ResteasyStartupListener - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy deleted file mode 100644 index 66519712839c..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/groovy/JaxrsAnnotationsInstrumentationTest.groovy +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import spock.lang.Unroll - -import jakarta.ws.rs.DELETE -import jakarta.ws.rs.GET -import jakarta.ws.rs.HEAD -import jakarta.ws.rs.OPTIONS -import jakarta.ws.rs.POST -import jakarta.ws.rs.PUT -import jakarta.ws.rs.Path - -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassName - -class JaxrsAnnotationsInstrumentationTest extends AgentInstrumentationSpecification { - - @Unroll - def "span named '#paramName' from annotations on class '#className' when is not root span"() { - setup: - runWithHttpServerSpan { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET " + paramName - kind SERVER - hasNoParent() - attributes { - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_ROUTE" paramName - "$ErrorAttributes.ERROR_TYPE" "_OTHER" - } - } - span(1) { - name "${className}.call" - childOf span(0) - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" obj.getClass().getName() - "$CodeIncubatingAttributes.CODE_FUNCTION" "call" - } - } - } - } - - when: "multiple calls to the same method" - runWithHttpServerSpan { - (1..10).each { - obj.call() - } - } - then: "doesn't increase the cache size" - - where: - paramName | obj - "/a" | new Jax() { - @Path("/a") - void call() { - } - } - "/b" | new Jax() { - @GET - @Path("/b") - void call() { - } - } - "/interface/c" | new InterfaceWithPath() { - @POST - @Path("/c") - void call() { - } - } - "/interface" | new InterfaceWithPath() { - @HEAD - void call() { - } - } - "/abstract/d" | new AbstractClassWithPath() { - @POST - @Path("/d") - void call() { - } - } - "/abstract" | new AbstractClassWithPath() { - @PUT - void call() { - } - } - "/child/e" | new ChildClassWithPath() { - @OPTIONS - @Path("/e") - void call() { - } - } - "/child/call" | new ChildClassWithPath() { - @DELETE - void call() { - } - } - "/child/call" | new ChildClassWithPath() - "/child/call" | new JavaInterfaces.ChildClassOnInterface() - "/child/call" | new JavaInterfaces.DefaultChildClassOnInterface() - - className = getClassName(obj.class) - } - - def "no annotations has no effect"() { - setup: - runWithHttpServerSpan { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind SERVER - attributes { - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$ErrorAttributes.ERROR_TYPE" "_OTHER" - } - } - } - } - - where: - obj | _ - new Jax() { - void call() { - } - } | _ - } - - interface Jax { - void call() - } - - @Path("/interface") - interface InterfaceWithPath extends Jax { - @GET - void call() - } - - @Path("/abstract") - static abstract class AbstractClassWithPath implements Jax { - @PUT - abstract void call() - } - - @Path("child") - static class ChildClassWithPath extends AbstractClassWithPath { - @Path("call") - @POST - void call() { - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/JavaInterfaces.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JavaInterfaces.java similarity index 94% rename from instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/JavaInterfaces.java rename to instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JavaInterfaces.java index 868a64488f44..20dd7885d4f4 100644 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/JavaInterfaces.java +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JavaInterfaces.java @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JaxRs3AnnotationsInstrumentationTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JaxRs3AnnotationsInstrumentationTest.java new file mode 100644 index 000000000000..d309f5ece149 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JaxRs3AnnotationsInstrumentationTest.java @@ -0,0 +1,174 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassName; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_ROUTE; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0.JavaInterfaces.Jax; +import io.opentelemetry.semconv.ErrorAttributes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HEAD; +import jakarta.ws.rs.OPTIONS; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class JaxRs3AnnotationsInstrumentationTest { + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static Stream provideArguments() { + return Stream.of( + Arguments.of( + "/a", + new Jax() { + @Path("/a") + @Override + public void call() {} + }), + Arguments.of( + "/b", + new Jax() { + @GET + @Path("/b") + @Override + public void call() {} + }), + Arguments.of( + "/interface/c", + new InterfaceWithPath() { + @POST + @Path("/c") + @Override + public void call() {} + }), + Arguments.of( + "/interface", + new InterfaceWithPath() { + @HEAD + @Override + public void call() {} + }), + Arguments.of( + "/abstract/d", + new AbstractClassWithPath() { + @POST + @Path("/d") + @Override + public void call() {} + }), + Arguments.of( + "/abstract", + new AbstractClassWithPath() { + @PUT + @Override + public void call() {} + }), + Arguments.of( + "/child/e", + new ChildClassWithPath() { + @OPTIONS + @Path("/e") + @Override + public void call() {} + }), + Arguments.of( + "/child/call", + new ChildClassWithPath() { + @DELETE + @Override + public void call() {} + }), + Arguments.of("/child/call", new ChildClassWithPath()), + Arguments.of("/child/call", new JavaInterfaces.ChildClassOnInterface()), + Arguments.of("/child/call", new JavaInterfaces.DefaultChildClassOnInterface())); + } + + @ParameterizedTest + @MethodSource("provideArguments") + void createSpanForAnnotatedMethod(String path, Jax action) { + String className = getClassName(action.getClass()); + testing.runWithHttpServerSpan(action::call); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + path) + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(HTTP_REQUEST_METHOD, "GET"), + equalTo(HTTP_ROUTE, path), + equalTo(ERROR_TYPE, ErrorAttributes.ErrorTypeValues.OTHER)), + span -> + span.hasName(className + ".call") + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(CODE_NAMESPACE, action.getClass().getName()), + equalTo(CODE_FUNCTION, "call")))); + } + + @Test + void notAnnotatedMethod() { + Jax action = + new Jax() { + @Override + public void call() {} + }; + testing.runWithHttpServerSpan(action::call); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(HTTP_REQUEST_METHOD, "GET"), + equalTo(ERROR_TYPE, ErrorAttributes.ErrorTypeValues.OTHER)))); + } + + @Path("/interface") + interface InterfaceWithPath extends Jax { + @GET + @Override + void call(); + } + + @Path("/abstract") + abstract static class AbstractClassWithPath implements Jax { + @PUT + @Override + public abstract void call(); + } + + @Path("child") + static class ChildClassWithPath extends AbstractClassWithPath { + @Path("call") + @POST + @Override + public void call() {} + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy deleted file mode 100644 index ede5e5618a0b..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsFilterTest.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import jakarta.ws.rs.container.ContainerRequestContext -import jakarta.ws.rs.container.ContainerRequestFilter -import jakarta.ws.rs.container.PreMatching -import jakarta.ws.rs.core.MediaType -import jakarta.ws.rs.core.Response -import jakarta.ws.rs.ext.Provider -import spock.lang.Shared -import spock.lang.Unroll - -@Unroll -abstract class JaxRsFilterTest extends AbstractJaxRsFilterTest { - - @Shared - SimpleRequestFilter simpleRequestFilter = new SimpleRequestFilter() - - @Shared - PrematchRequestFilter prematchRequestFilter = new PrematchRequestFilter() - - @Override - void setAbortStatus(boolean abortNormal, boolean abortPrematch) { - simpleRequestFilter.abort = abortNormal - prematchRequestFilter.abort = abortPrematch - } - - @Provider - static class SimpleRequestFilter implements ContainerRequestFilter { - boolean abort = false - - @Override - void filter(ContainerRequestContext requestContext) throws IOException { - if (abort) { - requestContext.abortWith( - Response.status(Response.Status.UNAUTHORIZED) - .entity("Aborted") - .type(MediaType.TEXT_PLAIN_TYPE) - .build()) - } - } - } - - @Provider - @PreMatching - static class PrematchRequestFilter implements ContainerRequestFilter { - boolean abort = false - - @Override - void filter(ContainerRequestContext requestContext) throws IOException { - if (abort) { - requestContext.abortWith( - Response.status(Response.Status.UNAUTHORIZED) - .entity("Aborted Prematch") - .type(MediaType.TEXT_PLAIN_TYPE) - .build()) - } - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy deleted file mode 100644 index 97391da68a1e..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsHttpServerTest.groovy +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.TimeUnit -import test.JaxRsTestResource - -abstract class JaxRsHttpServerTest extends AbstractJaxRsHttpServerTest { - - def setup() { - // reset the barrier to avoid a failing test breaking subsequent tests - JaxRsTestResource.BARRIER.reset() - } - - @Override - void awaitBarrier(int amount, TimeUnit timeUnit) { - JaxRsTestResource.BARRIER.await(amount, timeUnit) - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy deleted file mode 100644 index e817cb56e050..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/JaxRsJettyHttpServerTest.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.webapp.WebAppContext - -import static org.eclipse.jetty.util.resource.Resource.newResource - -abstract class JaxRsJettyHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - WebAppContext webAppContext = new WebAppContext() - webAppContext.setContextPath("/") - // set up test application - webAppContext.setBaseResource(newResource("src/test/webapp")) - - def jettyServer = new Server(port) - jettyServer.connectors.each { - it.setHost('localhost') - } - - jettyServer.setHandler(webAppContext) - jettyServer.start() - - return jettyServer - } - - @Override - void stopServer(Server server) { - server.stop() - server.destroy() - } - - @Override - String getContextPath() { - "/rest-app" - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy deleted file mode 100644 index b069ad507756..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/groovy/test/JaxRsTestResource.groovy +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import jakarta.ws.rs.ApplicationPath -import jakarta.ws.rs.GET -import jakarta.ws.rs.HeaderParam -import jakarta.ws.rs.Path -import jakarta.ws.rs.PathParam -import jakarta.ws.rs.QueryParam -import jakarta.ws.rs.container.AsyncResponse -import jakarta.ws.rs.container.Suspended -import jakarta.ws.rs.core.Application -import jakarta.ws.rs.core.Context -import jakarta.ws.rs.core.Response -import jakarta.ws.rs.core.UriInfo -import jakarta.ws.rs.ext.ExceptionMapper -import java.util.concurrent.CompletableFuture -import java.util.concurrent.CompletionStage -import java.util.concurrent.CyclicBarrier - -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS -import static java.util.concurrent.TimeUnit.SECONDS - -@Path("") -class JaxRsTestResource { - @Path("/success") - @GET - String success() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } - - @Path("query") - @GET - String query_param(@QueryParam("some") String param) { - HttpServerTest.controller(QUERY_PARAM) { - "some=$param" - } - } - - @Path("redirect") - @GET - Response redirect(@Context UriInfo uriInfo) { - HttpServerTest.controller(REDIRECT) { - Response.status(Response.Status.FOUND) - .location(uriInfo.relativize(new URI(REDIRECT.body))) - .build() - } - } - - @Path("error-status") - @GET - Response error() { - HttpServerTest.controller(ERROR) { - Response.status(ERROR.status) - .entity(ERROR.body) - .build() - } - } - - @Path("exception") - @GET - Object exception() { - HttpServerTest.controller(EXCEPTION) { - throw new Exception(EXCEPTION.body) - } - } - - @Path("path/{id}/param") - @GET - String path_param(@PathParam("id") int id) { - HttpServerTest.controller(PATH_PARAM) { - id - } - } - - @GET - @Path("captureHeaders") - Response capture_headers(@HeaderParam("X-Test-Request") String header) { - HttpServerTest.controller(CAPTURE_HEADERS) { - Response.status(CAPTURE_HEADERS.status) - .header("X-Test-Response", header) - .entity(CAPTURE_HEADERS.body) - .build() - } - } - - @Path("/child") - @GET - void indexed_child(@Context UriInfo uriInfo, @Suspended AsyncResponse response) { - def parameters = uriInfo.queryParameters - - CompletableFuture.runAsync({ - HttpServerTest.controller(INDEXED_CHILD) { - INDEXED_CHILD.collectSpanAttributes { parameters.getFirst(it) } - response.resume("") - } - }) - } - - static final BARRIER = new CyclicBarrier(2) - - @Path("async") - @GET - void asyncOp(@Suspended AsyncResponse response, @QueryParam("action") String action) { - CompletableFuture.runAsync({ - // await for the test method to verify that there are no spans yet - BARRIER.await(10, SECONDS) - - switch (action) { - case "succeed": - response.resume("success") - break - case "throw": - response.resume(new Exception("failure")) - break - case "cancel": - response.cancel() - break - default: - response.resume(new AssertionError((Object) ("invalid action value: " + action))) - break - } - }) - } - - @Path("async-completion-stage") - @GET - CompletionStage jaxRs21Async(@QueryParam("action") String action) { - def result = new CompletableFuture() - CompletableFuture.runAsync({ - // await for the test method to verify that there are no spans yet - BARRIER.await(10, SECONDS) - - switch (action) { - case "succeed": - result.complete("success") - break - case "throw": - result.completeExceptionally(new Exception("failure")) - break - default: - result.completeExceptionally(new AssertionError((Object) ("invalid action value: " + action))) - break - } - }) - result - } -} - -@Path("test-resource-super") -class JaxRsSuperClassTestResource extends JaxRsSuperClassTestResourceSuper { -} - -class JaxRsSuperClassTestResourceSuper { - @GET - Object call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -class JaxRsInterfaceClassTestResource extends JaxRsInterfaceClassTestResourceSuper implements JaxRsInterface { -} - -@Path("test-resource-interface") -interface JaxRsInterface { - @Path("call") - @GET - Object call() -} - -class JaxRsInterfaceClassTestResourceSuper { - Object call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -@Path("test-sub-resource-locator") -class JaxRsSubResourceLocatorTestResource { - @Path("call") - Object call() { - HttpServerTest.controller(SUCCESS) { - return new SubResource() - } - } -} - -class SubResource { - @Path("sub") - @GET - String call() { - HttpServerTest.controller(SUCCESS) { - SUCCESS.body - } - } -} - -class JaxRsTestExceptionMapper implements ExceptionMapper { - @Override - Response toResponse(Exception exception) { - return Response.status(500) - .entity(exception.message) - .build() - } -} - -class JaxRsTestApplication extends Application { - @Override - Set> getClasses() { - def classes = new HashSet() - classes.add(JaxRsTestResource) - classes.add(JaxRsSuperClassTestResource) - classes.add(JaxRsInterfaceClassTestResource) - classes.add(JaxRsSubResourceLocatorTestResource) - classes.add(JaxRsTestExceptionMapper) - return classes - } -} - -@ApplicationPath("/rest-app") -class JaxRsApplicationPathTestApplication extends JaxRsTestApplication { -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsFilterTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsFilterTest.java new file mode 100644 index 000000000000..0c9cba8aa82e --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsFilterTest.java @@ -0,0 +1,59 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.AbstractJaxRsFilterTest; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestFilter; +import jakarta.ws.rs.container.PreMatching; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.Provider; + +public abstract class JaxRsFilterTest extends AbstractJaxRsFilterTest { + + protected final SimpleRequestFilter simpleRequestFilter = new SimpleRequestFilter(); + protected final PrematchRequestFilter prematchRequestFilter = new PrematchRequestFilter(); + + @Override + protected void setAbortStatus(boolean abortNormal, boolean abortPrematch) { + simpleRequestFilter.abort = abortNormal; + prematchRequestFilter.abort = abortPrematch; + } + + @Provider + protected static class SimpleRequestFilter implements ContainerRequestFilter { + boolean abort = false; + + @Override + public void filter(ContainerRequestContext requestContext) { + if (abort) { + requestContext.abortWith( + Response.status(Response.Status.UNAUTHORIZED) + .entity("Aborted") + .type(MediaType.TEXT_PLAIN_TYPE) + .build()); + } + } + } + + @Provider + @PreMatching + protected static class PrematchRequestFilter implements ContainerRequestFilter { + boolean abort = false; + + @Override + public void filter(ContainerRequestContext requestContext) { + if (abort) { + requestContext.abortWith( + Response.status(Response.Status.UNAUTHORIZED) + .entity("Aborted Prematch") + .type(MediaType.TEXT_PLAIN_TYPE) + .build()); + } + } + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsHttpServerTest.java new file mode 100644 index 000000000000..9b01fe0e0fa7 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsHttpServerTest.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.AbstractJaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.JaxRsTestResource; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.BeforeEach; + +public abstract class JaxRsHttpServerTest extends AbstractJaxRsHttpServerTest { + + @BeforeEach + void setup() { + // reset the barrier to avoid a failing test breaking subsequent tests + JaxRsTestResource.BARRIER.reset(); + } + + @Override + protected void awaitBarrier(int amount, TimeUnit timeUnit) + throws BrokenBarrierException, InterruptedException, TimeoutException { + JaxRsTestResource.BARRIER.await(amount, timeUnit); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsJettyHttpServerTest.java new file mode 100644 index 000000000000..71e981c12052 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/JaxRsJettyHttpServerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0; + +import static org.eclipse.jetty.util.resource.Resource.newResource; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; + +public abstract class JaxRsJettyHttpServerTest extends JaxRsHttpServerTest { + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setContextPath("/rest-app"); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } + + @Override + protected Server setupServer() throws Exception { + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath("/"); + // set up test application + webAppContext.setBaseResource(newResource("src/test/webapp")); + + Server jettyServer = new Server(port); + jettyServer.setHandler(webAppContext); + jettyServer.start(); + + return jettyServer; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + server.destroy(); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsApplicationPathTestApplication.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsApplicationPathTestApplication.java new file mode 100644 index 000000000000..e372484b6bfd --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsApplicationPathTestApplication.java @@ -0,0 +1,11 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import jakarta.ws.rs.ApplicationPath; + +@ApplicationPath("/rest-app") +public class JaxRsApplicationPathTestApplication extends JaxRsTestApplication {} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterface.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterface.java new file mode 100644 index 000000000000..20d3292319d8 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterface.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +@Path("test-resource-interface") +public interface JaxRsInterface { + @Path("call") + @GET + Object call(); +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResource.java new file mode 100644 index 000000000000..1cbc0013bf96 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResource.java @@ -0,0 +1,9 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +public class JaxRsInterfaceClassTestResource extends JaxRsInterfaceClassTestResourceSuper + implements JaxRsInterface {} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResourceSuper.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResourceSuper.java new file mode 100644 index 000000000000..a0f7166a39a4 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsInterfaceClassTestResourceSuper.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +public class JaxRsInterfaceClassTestResourceSuper { + public Object call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSubResourceLocatorTestResource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSubResourceLocatorTestResource.java new file mode 100644 index 000000000000..896bbded13d9 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSubResourceLocatorTestResource.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import jakarta.ws.rs.Path; + +@Path("test-sub-resource-locator") +public class JaxRsSubResourceLocatorTestResource { + @Path("call") + public Object call() { + return controller(SUCCESS, SubResource::new); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResource.java new file mode 100644 index 000000000000..b35e4dc894f0 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResource.java @@ -0,0 +1,11 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import jakarta.ws.rs.Path; + +@Path("test-resource-super") +public class JaxRsSuperClassTestResource extends JaxRsSuperClassTestResourceSuper {} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResourceSuper.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResourceSuper.java new file mode 100644 index 000000000000..19b480507ab5 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsSuperClassTestResourceSuper.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import jakarta.ws.rs.GET; + +public class JaxRsSuperClassTestResourceSuper { + @GET + public Object call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestApplication.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestApplication.java new file mode 100644 index 000000000000..8c851ef27bb1 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestApplication.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import jakarta.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; + +public class JaxRsTestApplication extends Application { + @Override + public Set> getClasses() { + Set> classes = new HashSet<>(); + classes.add(JaxRsTestResource.class); + classes.add(JaxRsSuperClassTestResource.class); + classes.add(JaxRsInterfaceClassTestResource.class); + classes.add(JaxRsSubResourceLocatorTestResource.class); + classes.add(JaxRsTestExceptionMapper.class); + return classes; + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestExceptionMapper.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestExceptionMapper.java new file mode 100644 index 000000000000..5f677b8d33cd --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestExceptionMapper.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; + +public class JaxRsTestExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(Exception exception) { + return Response.status(500).entity(exception.getMessage()).build(); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestResource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestResource.java new file mode 100644 index 000000000000..cb27d90828b4 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/JaxRsTestResource.java @@ -0,0 +1,174 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.container.Suspended; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CyclicBarrier; + +@SuppressWarnings("IdentifierName") +@Path("") +public class JaxRsTestResource { + @Path("/success") + @GET + public String success() { + return controller(SUCCESS, SUCCESS::getBody); + } + + @Path("query") + @GET + public String query_param(@QueryParam("some") String param) { + return controller(QUERY_PARAM, () -> "some=" + param); + } + + @Path("redirect") + @GET + public Response redirect(@Context UriInfo uriInfo) throws URISyntaxException { + return controller( + SUCCESS, + () -> + Response.status(Response.Status.FOUND) + .location(uriInfo.relativize(new URI(REDIRECT.getBody()))) + .build()); + } + + @Path("error-status") + @GET + public Response error() { + return controller( + SUCCESS, () -> Response.status(ERROR.getStatus()).entity(ERROR.getBody()).build()); + } + + @Path("exception") + @GET + public Object exception() { + return controller( + SUCCESS, + () -> { + throw new IllegalStateException(EXCEPTION.getBody()); + }); + } + + @Path("path/{id}/param") + @GET + public String path_param(@PathParam("id") int id) { + return controller(PATH_PARAM, () -> String.valueOf(id)); + } + + @GET + @Path("captureHeaders") + public Response capture_headers(@HeaderParam("X-Test-Request") String header) { + return controller( + CAPTURE_HEADERS, + () -> + Response.status(CAPTURE_HEADERS.getStatus()) + .header("X-Test-Response", header) + .entity(CAPTURE_HEADERS.getBody()) + .build()); + } + + @Path("/child") + @GET + public void indexed_child(@Context UriInfo uriInfo, @Suspended AsyncResponse response) { + MultivaluedMap parameters = uriInfo.getQueryParameters(); + + CompletableFuture.runAsync( + () -> + controller( + INDEXED_CHILD, + () -> { + INDEXED_CHILD.collectSpanAttributes(parameters::getFirst); + response.resume(""); + })); + } + + public static final CyclicBarrier BARRIER = new CyclicBarrier(2); + + @Path("async") + @GET + public void asyncOp(@Suspended AsyncResponse response, @QueryParam("action") String action) { + CompletableFuture.runAsync( + () -> { + // await for the test method to verify that there are no spans yet + try { + BARRIER.await(10, SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception exception) { + throw new IllegalStateException(exception); + } + + switch (action) { + case "succeed": + response.resume("success"); + break; + case "throw": + response.resume(new IllegalStateException("failure")); + break; + case "cancel": + response.cancel(); + break; + default: + response.resume(new AssertionError("invalid action value: " + action)); + break; + } + }); + } + + @Path("async-completion-stage") + @GET + public CompletionStage jaxRs21Async(@QueryParam("action") String action) { + CompletableFuture result = new CompletableFuture<>(); + CompletableFuture.runAsync( + () -> { + // await for the test method to verify that there are no spans yet + try { + BARRIER.await(10, SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception exception) { + throw new IllegalStateException(exception); + } + + switch (action) { + case "succeed": + result.complete("success"); + break; + case "throw": + result.completeExceptionally(new IllegalStateException("failure")); + break; + default: + result.completeExceptionally(new AssertionError("invalid action value: " + action)); + break; + } + }); + return result; + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/Resource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/Resource.java similarity index 94% rename from instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/Resource.java rename to instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/Resource.java index 1b9e231c6300..bae7536b2d7b 100644 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/Resource.java +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/Resource.java @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/SubResource.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/SubResource.java new file mode 100644 index 000000000000..e172631b4b3f --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/v3_0/test/SubResource.java @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs.v3_0.test; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +public class SubResource { + @Path("sub") + @GET + public String call() { + return controller(SUCCESS, SUCCESS::getBody); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyFilterTest.groovy deleted file mode 100644 index 0d64d1242f05..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyFilterTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import jakarta.ws.rs.core.Application -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.servlet.ServletHolder -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class JerseyFilterTest extends JaxRsFilterTest implements HttpServerTestTrait { - - def setupSpec() { - setupServer() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - Server startServer(int port) { - def servlet = new ServletContainer(ResourceConfig.forApplication(new TestApplication())) - - def handler = new ServletContextHandler(ServletContextHandler.SESSIONS) - handler.setContextPath("/") - handler.addServlet(new ServletHolder(servlet), "/*") - - def server = new Server(port) - server.setHandler(handler) - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - boolean runsOnServer() { - true - } - - @Override - String defaultServerRoute() { - "/*" - } - - @Override - def makeRequest(String path) { - AggregatedHttpResponse response = client.post(address.resolve(path).toString(), "").aggregate().join() - - return [response.contentUtf8(), response.status().code()] - } - - class TestApplication extends Application { - @Override - Set> getClasses() { - def classes = new HashSet() - classes.add(Test1) - classes.add(Test2) - classes.add(Test3) - return classes - } - - @Override - Set getSingletons() { - def singletons = new HashSet() - singletons.add(simpleRequestFilter) - singletons.add(prematchRequestFilter) - return singletons - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy deleted file mode 100644 index 05d37cd00ef2..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyHttpServerTest.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.servlet.ServletHolder -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer -import test.JaxRsTestApplication - -class JerseyHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - def servlet = new ServletContainer(ResourceConfig.forApplicationClass(JaxRsTestApplication)) - - def handler = new ServletContextHandler(ServletContextHandler.SESSIONS) - handler.setContextPath("/") - handler.addServlet(new ServletHolder(servlet), "/*") - - def server = new Server(port) - server.setHandler(handler) - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } - - @Override - boolean asyncCancelHasSendError() { - true - } - - @Override - boolean testInterfaceMethodWithPath() { - // disables a test that jersey deems invalid - false - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy deleted file mode 100644 index 97c4c1c28642..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyJettyHttpServerTest.groovy +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class JerseyJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - @Override - boolean asyncCancelHasSendError() { - true - } - - @Override - boolean testInterfaceMethodWithPath() { - // disables a test that jersey deems invalid - false - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyStartupListener.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyStartupListener.groovy deleted file mode 100644 index fd73b0918d69..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/groovy/JerseyStartupListener.groovy +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import jakarta.servlet.ServletContextEvent -import jakarta.servlet.ServletContextListener -import org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer -import test.JaxRsApplicationPathTestApplication - -// ServletContainerInitializer isn't automatically called due to the way this test is set up -// so we call it ourself -class JerseyStartupListener implements ServletContextListener { - @Override - void contextInitialized(ServletContextEvent servletContextEvent) { - new JerseyServletContainerInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication), - servletContextEvent.getServletContext()) - } - - @Override - void contextDestroyed(ServletContextEvent servletContextEvent) { - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyFilterTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyFilterTest.java new file mode 100644 index 000000000000..c330b30ab127 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyFilterTest.java @@ -0,0 +1,100 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import jakarta.servlet.Servlet; +import jakarta.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Server setupServer() throws Exception { + Servlet servlet = new ServletContainer(ResourceConfig.forApplication(new TestApplication())); + + ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); + handler.setContextPath("/"); + handler.addServlet(new ServletHolder(servlet), "/*"); + + Server server = new Server(port); + server.setHandler(handler); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + } + + @Override + protected String getContextPath() { + return "/*"; + } + + @Override + protected boolean runsOnServer() { + return true; + } + + @Override + protected String defaultServerRoute() { + return "/*"; + } + + @Override + protected TestResponse makeRequest(String url) { + AggregatedHttpResponse response = + client.post(address.resolve(url).toString(), "").aggregate().join(); + return new TestResponse(response.contentUtf8(), response.status().code()); + } + + class TestApplication extends Application { + @Override + public Set> getClasses() { + Set> classes = new HashSet<>(); + classes.add(Resource.Test1.class); + classes.add(Resource.Test2.class); + classes.add(Resource.Test3.class); + return classes; + } + + @Override + public Set getSingletons() { + Set singletons = new HashSet<>(); + singletons.add(simpleRequestFilter); + singletons.add(prematchRequestFilter); + return singletons; + } + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyHttpServerTest.java new file mode 100644 index 000000000000..d5a3e1f35c64 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyHttpServerTest.java @@ -0,0 +1,71 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import jakarta.servlet.Servlet; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected Server setupServer() throws Exception { + Servlet servlet = + new ServletContainer(ResourceConfig.forApplicationClass(JaxRsTestApplication.class)); + + ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); + handler.setContextPath("/"); + handler.addServlet(new ServletHolder(servlet), "/*"); + + Server server = new Server(port); + server.setHandler(handler); + server.start(); + + return server; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + } + + @Override + protected boolean asyncCancelHasSendError() { + return true; + } + + @Override + protected boolean testInterfaceMethodWithPath() { + // disables a test that jersey deems invalid + return false; + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyJettyHttpServerTest.java new file mode 100644 index 000000000000..93944d10acdd --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyJettyHttpServerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JerseyJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } + + @Override + protected boolean asyncCancelHasSendError() { + return true; + } + + @Override + protected boolean testInterfaceMethodWithPath() { + // disables a test that jersey deems invalid + return false; + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyStartupListener.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyStartupListener.java new file mode 100644 index 000000000000..6cb75f5b2fb9 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/JerseyStartupListener.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.JaxRsApplicationPathTestApplication; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.ServletException; +import java.util.Collections; +import org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer; + +// ServletContainerInitializer isn't automatically called due to the way this test is set up, +// so we call it ourselves +public class JerseyStartupListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + try { + new JerseyServletContainerInitializer() + .onStartup( + Collections.singleton(JaxRsApplicationPathTestApplication.class), + servletContextEvent.getServletContext()); + } catch (ServletException exception) { + throw new IllegalStateException(exception); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) {} +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/webapp/WEB-INF/web.xml index 5b492283ea2f..f1a6f5c52c7d 100644 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-jersey-3.0/javaagent/src/test/webapp/WEB-INF/web.xml @@ -5,6 +5,6 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> - JerseyStartupListener + io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0.JerseyStartupListener - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy deleted file mode 100644 index 80c0fdb9469c..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyFilterTest.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import jakarta.ws.rs.core.MediaType -import org.jboss.resteasy.mock.MockDispatcherFactory -import org.jboss.resteasy.mock.MockHttpRequest -import org.jboss.resteasy.mock.MockHttpResponse -import spock.lang.Shared - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -class ResteasyFilterTest extends JaxRsFilterTest { - @Shared - def dispatcher - - def setupSpec() { - dispatcher = MockDispatcherFactory.createDispatcher() - def registry = dispatcher.getRegistry() - registry.addSingletonResource(new Test1()) - registry.addSingletonResource(new Test2()) - registry.addSingletonResource(new Test3()) - - dispatcher.getProviderFactory().register(simpleRequestFilter) - dispatcher.getProviderFactory().register(prematchRequestFilter) - } - - @Override - def makeRequest(String url) { - MockHttpRequest request = MockHttpRequest.post(url) - request.contentType(MediaType.TEXT_PLAIN_TYPE) - request.content(new byte[0]) - - MockHttpResponse response = new MockHttpResponse() - dispatcher.invoke(request, response) - - return [response.contentAsString, response.status] - } - -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy deleted file mode 100644 index 1ea11b42295c..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyHttpServerTest.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.api.internal.HttpConstants -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import io.undertow.Undertow -import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer -import test.JaxRsTestApplication - -class ResteasyHttpServerTest extends JaxRsHttpServerTest { - - @Override - String getContextPath() { - "/resteasy-context" - } - - @Override - UndertowJaxrsServer startServer(int port) { - def server = new UndertowJaxrsServer() - server.deploy(JaxRsTestApplication, getContextPath()) - server.start(Undertow.builder() - .addHttpListener(port, "localhost")) - return server - } - - @Override - void stopServer(UndertowJaxrsServer server) { - server.stop() - } - - // resteasy 3.0.x does not support JAX-RS 2.1 - boolean shouldTestCompletableStageAsync() { - false - } - - @Override - String expectedHttpRoute(ServerEndpoint endpoint, String method) { - if (method == HttpConstants._OTHER) { - return "${getContextPath()}/*" - } - return super.expectedHttpRoute(endpoint, method) - } - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy deleted file mode 100644 index 8d92d379711a..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyJettyHttpServerTest.groovy +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { - - @Override - int getResponseCodeOnNonStandardHttpMethod() { - 500 - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy deleted file mode 100644 index e1af7700cd66..000000000000 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/groovy/ResteasyStartupListener.groovy +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer -import test.JaxRsApplicationPathTestApplication - -import jakarta.servlet.ServletContextEvent -import jakarta.servlet.ServletContextListener - -// ServletContainerInitializer isn't automatically called due to the way this test is set up -// so we call it ourself -class ResteasyStartupListener implements ServletContextListener { - @Override - void contextInitialized(ServletContextEvent servletContextEvent) { - new ResteasyServletInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication), - servletContextEvent.getServletContext()) - } - - @Override - void contextDestroyed(ServletContextEvent servletContextEvent) { - } -} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyFilterTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyFilterTest.java new file mode 100644 index 000000000000..09f55b6ffaa1 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyFilterTest.java @@ -0,0 +1,72 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsFilterTest; +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.Resource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import jakarta.ws.rs.core.MediaType; +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.mock.MockHttpRequest; +import org.jboss.resteasy.mock.MockHttpResponse; +import org.jboss.resteasy.spi.Dispatcher; +import org.jboss.resteasy.spi.Registry; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyFilterTest extends JaxRsFilterTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + private Dispatcher dispatcher; + + @BeforeAll + void setUp() { + startServer(); + } + + @AfterAll + void cleanUp() { + cleanupServer(); + } + + @Override + protected Void setupServer() { + dispatcher = MockDispatcherFactory.createDispatcher(); + Registry registry = dispatcher.getRegistry(); + registry.addSingletonResource(new Resource.Test1()); + registry.addSingletonResource(new Resource.Test2()); + registry.addSingletonResource(new Resource.Test3()); + + dispatcher.getProviderFactory().register(simpleRequestFilter); + dispatcher.getProviderFactory().register(prematchRequestFilter); + + return null; + } + + @Override + protected void stopServer(Void server) {} + + @Override + protected String getContextPath() { + return ""; + } + + @Override + protected TestResponse makeRequest(String url) throws Exception { + MockHttpRequest request = MockHttpRequest.post(url); + ; + request.contentType(MediaType.TEXT_PLAIN_TYPE); + request.content(new byte[0]); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + + return new TestResponse(response.getContentAsString(), response.getStatus()); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyHttpServerTest.java new file mode 100644 index 000000000000..9d98c6e47072 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyHttpServerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsHttpServerTest; +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.JaxRsTestApplication; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import io.undertow.Undertow; +import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyHttpServerTest extends JaxRsHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected UndertowJaxrsServer setupServer() { + UndertowJaxrsServer server = new UndertowJaxrsServer(); + server.deploy(JaxRsTestApplication.class, getContextPath()); + server.start(Undertow.builder().addHttpListener(port, "localhost")); + + return server; + } + + @Override + protected void stopServer(UndertowJaxrsServer server) { + server.stop(); + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setContextPath("/resteasy-context"); + options.setResponseCodeOnNonStandardHttpMethod(500); + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (HttpConstants._OTHER.equals(method)) { + return getContextPath() + "/*"; + } + return expectedHttpRoute(endpoint, method); + }); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyJettyHttpServerTest.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyJettyHttpServerTest.java new file mode 100644 index 000000000000..8aab21abc9fa --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyJettyHttpServerTest.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.JaxRsJettyHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest { + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent(); + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setResponseCodeOnNonStandardHttpMethod(500); + } +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyStartupListener.java b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyStartupListener.java new file mode 100644 index 000000000000..a6167270f1cc --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v3_0/ResteasyStartupListener.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0; + +import io.opentelemetry.instrumentation.jaxrs.v3_0.test.JaxRsApplicationPathTestApplication; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.ServletException; +import java.util.Collections; +import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer; + +// ServletContainerInitializer isn't automatically called due to the way this test is set up, +// so we call it ourselves +public class ResteasyStartupListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + try { + new ResteasyServletInitializer() + .onStartup( + Collections.singleton(JaxRsApplicationPathTestApplication.class), + servletContextEvent.getServletContext()); + } catch (ServletException exception) { + throw new IllegalStateException(exception); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) {} +} diff --git a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/webapp/WEB-INF/web.xml b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/webapp/WEB-INF/web.xml index 459aba5d0538..cc3d808786d1 100644 --- a/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/webapp/WEB-INF/web.xml +++ b/instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-resteasy-6.0/javaagent/src/test/webapp/WEB-INF/web.xml @@ -5,6 +5,6 @@ xsi:schemaLocation= "https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"> - ResteasyStartupListener + io.opentelemetry.javaagent.instrumentation.jaxrs.v3_0.ResteasyStartupListener - \ No newline at end of file + diff --git a/instrumentation/jaxrs/jaxrs-common/testing/build.gradle.kts b/instrumentation/jaxrs/jaxrs-common/testing/build.gradle.kts index 98dff25fa857..a45243aa45a3 100644 --- a/instrumentation/jaxrs/jaxrs-common/testing/build.gradle.kts +++ b/instrumentation/jaxrs/jaxrs-common/testing/build.gradle.kts @@ -5,9 +5,7 @@ plugins { dependencies { api(project(":testing-common")) - implementation("org.apache.groovy:groovy") implementation("io.opentelemetry:opentelemetry-api") - implementation("org.spockframework:spock-core") implementation("org.slf4j:slf4j-api") implementation("ch.qos.logback:logback-classic") implementation("org.slf4j:log4j-over-slf4j") diff --git a/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsFilterTest.groovy b/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsFilterTest.groovy deleted file mode 100644 index 8b880f6c02e7..000000000000 --- a/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsFilterTest.groovy +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import org.junit.jupiter.api.Assumptions -import spock.lang.Unroll - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.api.trace.StatusCode.UNSET - -@Unroll -abstract class AbstractJaxRsFilterTest extends AgentInstrumentationSpecification { - - abstract makeRequest(String url) - - Tuple2 runRequest(String resource) { - if (runsOnServer()) { - return makeRequest(resource) - } - // start a trace because the test doesn't go through any servlet or other instrumentation. - return runWithHttpServerSpan { - makeRequest(resource) - } - } - - boolean testAbortPrematch() { - true - } - - boolean runsOnServer() { - false - } - - String defaultServerRoute() { - null - } - - abstract void setAbortStatus(boolean abortNormal, boolean abortPrematch) - - def "test #resource, #abortNormal, #abortPrematch"() { - Assumptions.assumeTrue(!abortPrematch || testAbortPrematch()) - - given: - setAbortStatus(abortNormal, abortPrematch) - def abort = abortNormal || abortPrematch - - when: - - def (responseText, responseStatus) = runRequest(resource) - - then: - responseText == expectedResponse - - if (abort) { - responseStatus == 401 // Response.Status.UNAUTHORIZED.statusCode - } else { - responseStatus == 200 // Response.Status.OK.statusCode - } - - def serverRoute = route ?: defaultServerRoute() - def method = runsOnServer() ? "POST" : "GET" - def expectedServerSpanName = serverRoute == null ? method : method + " " + serverRoute - - assertTraces(1) { - trace(0, 2) { - span(0) { - name expectedServerSpanName - kind SERVER - if (runsOnServer() && abortNormal) { - status UNSET - } - } - span(1) { - childOf span(0) - name controllerName - if (abortPrematch) { - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" "JaxRsFilterTest\$PrematchRequestFilter" - "$CodeIncubatingAttributes.CODE_FUNCTION" "filter" - } - } else { - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" ~/Resource[$]Test*/ - "$CodeIncubatingAttributes.CODE_FUNCTION" "hello" - } - } - } - } - } - - where: - resource | abortNormal | abortPrematch | route | controllerName | expectedResponse - "/test/hello/bob" | false | false | "/test/hello/{name}" | "Test1.hello" | "Test1 bob!" - "/test2/hello/bob" | false | false | "/test2/hello/{name}" | "Test2.hello" | "Test2 bob!" - "/test3/hi/bob" | false | false | "/test3/hi/{name}" | "Test3.hello" | "Test3 bob!" - - // Resteasy and Jersey give different resource class names for just the below case - // Resteasy returns "SubResource.class" - // Jersey returns "Test1.class - // "/test/hello/bob" | true | false | "/test/hello/{name}" | "Test1.hello" | "Aborted" - - "/test2/hello/bob" | true | false | "/test2/hello/{name}" | "Test2.hello" | "Aborted" - "/test3/hi/bob" | true | false | "/test3/hi/{name}" | "Test3.hello" | "Aborted" - "/test/hello/bob" | false | true | null | "PrematchRequestFilter.filter" | "Aborted Prematch" - "/test2/hello/bob" | false | true | null | "PrematchRequestFilter.filter" | "Aborted Prematch" - "/test3/hi/bob" | false | true | null | "PrematchRequestFilter.filter" | "Aborted Prematch" - } - - def "test nested call"() { - given: - setAbortStatus(false, false) - - when: - def (responseText, responseStatus) = runRequest(resource) - - then: - responseStatus == 200 // Response.Status.OK.statusCode - responseText == expectedResponse - - def method = runsOnServer() ? "POST" : "GET" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name method + " " + route - kind SERVER - if (!runsOnServer()) { - attributes { - "$HttpAttributes.HTTP_REQUEST_METHOD" method - "$HttpAttributes.HTTP_ROUTE" route - "$ErrorAttributes.ERROR_TYPE" "_OTHER" - } - } - } - span(1) { - childOf span(0) - name controller1Name - kind INTERNAL - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" ~/Resource[$]Test*/ - "$CodeIncubatingAttributes.CODE_FUNCTION" "nested" - } - } - } - } - - where: - resource | route | controller1Name | expectedResponse - "/test3/nested" | "/test3/nested" | "Test3.nested" | "Test3 nested!" - } -} diff --git a/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsHttpServerTest.groovy deleted file mode 100644 index 8625ff0d300f..000000000000 --- a/instrumentation/jaxrs/jaxrs-common/testing/src/main/groovy/AbstractJaxRsHttpServerTest.groovy +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestTrait -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint -import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes -import io.opentelemetry.semconv.ServerAttributes -import io.opentelemetry.semconv.ClientAttributes -import io.opentelemetry.semconv.UserAgentAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.NetworkAttributes -import io.opentelemetry.semconv.UrlAttributes -import spock.lang.Unroll - -import java.util.concurrent.TimeUnit - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.api.trace.StatusCode.ERROR -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS -import static java.util.concurrent.TimeUnit.SECONDS -import static org.junit.jupiter.api.Assumptions.assumeTrue - -abstract class AbstractJaxRsHttpServerTest extends HttpServerTest implements AgentTestTrait { - - abstract void awaitBarrier(int amount, TimeUnit timeUnit) - - def "test super method without @Path"() { - given: - def response = client.get(address.resolve("test-resource-super").toString()).aggregate().join() - - expect: - response.status().code() == SUCCESS.status - response.contentUtf8() == SUCCESS.body - - assertTraces(1) { - trace(0, 2) { - span(0) { - hasNoParent() - kind SERVER - name "GET " + getContextPath() + "/test-resource-super" - } - span(1) { - name "controller" - kind INTERNAL - childOf span(0) - } - } - } - } - - def "test interface method with @Path"() { - assumeTrue(testInterfaceMethodWithPath()) - - given: - def response = client.get(address.resolve("test-resource-interface/call").toString()).aggregate().join() - - expect: - response.status().code() == SUCCESS.status - response.contentUtf8() == SUCCESS.body - - assertTraces(1) { - trace(0, 2) { - span(0) { - hasNoParent() - kind SERVER - name "GET " + getContextPath() + "/test-resource-interface/call" - } - span(1) { - name "controller" - kind INTERNAL - childOf span(0) - } - } - } - } - - def "test sub resource locator"() { - given: - def response = client.get(address.resolve("test-sub-resource-locator/call/sub").toString()).aggregate().join() - - expect: - response.status().code() == SUCCESS.status - response.contentUtf8() == SUCCESS.body - - assertTraces(1) { - trace(0, 5) { - span(0) { - hasNoParent() - kind SERVER - name "GET " + getContextPath() + "/test-sub-resource-locator/call/sub" - } - span(1) { - name "JaxRsSubResourceLocatorTestResource.call" - kind INTERNAL - childOf span(0) - } - span(2) { - name "controller" - kind INTERNAL - childOf span(1) - } - span(3) { - name "SubResource.call" - kind INTERNAL - childOf span(0) - } - span(4) { - name "controller" - kind INTERNAL - childOf span(3) - } - } - } - } - - @Unroll - def "should handle #desc AsyncResponse"() { - given: - def url = address.resolve("async?action=${action}").toString() - - when: "async call is started" - def futureResponse = client.get(url).aggregate() - - then: "there are no traces yet" - assertTraces(0) { - } - - when: "barrier is released and resource class sends response" - awaitBarrier(10, SECONDS) - def response = futureResponse.join() - - then: - response.status().code() == statusCode - bodyPredicate(response.contentUtf8()) - - def spanCount = 2 - def hasSendError = asyncCancelHasSendError() && action == "cancel" - if (hasSendError) { - spanCount++ - } - assertTraces(1) { - trace(0, spanCount) { - asyncServerSpan(it, 0, url, statusCode) - handlerSpan(it, 1, span(0), "asyncOp", isCancelled, isError, errorMessage) - if (hasSendError) { - sendErrorSpan(it, 2, span(1)) - } - } - } - - where: - desc | action | statusCode | bodyPredicate | isCancelled | isError | errorMessage - "successful" | "succeed" | 200 | { it == "success" } | false | false | null - "failing" | "throw" | 500 | { it == "failure" } | false | true | "failure" - "canceled" | "cancel" | 503 | { it instanceof String } | true | false | null - } - - @Unroll - def "should handle #desc CompletionStage (JAX-RS 2.1+ only)"() { - assumeTrue(shouldTestCompletableStageAsync()) - given: - def url = address.resolve("async-completion-stage?action=${action}").toString() - - when: "async call is started" - def futureResponse = client.get(url).aggregate() - - then: "there are no traces yet" - assertTraces(0) { - } - - when: "barrier is released and resource class sends response" - awaitBarrier(10, SECONDS) - def response = futureResponse.join() - - then: - response.status().code() == statusCode - bodyPredicate(response.contentUtf8()) - - assertTraces(1) { - trace(0, 2) { - asyncServerSpan(it, 0, url, statusCode) - handlerSpan(it, 1, span(0), "jaxRs21Async", false, isError, errorMessage) - } - } - - where: - desc | action | statusCode | bodyPredicate | isError | errorMessage - "successful" | "succeed" | 200 | { it == "success" } | false | null - "failing" | "throw" | 500 | { it == "failure" } | true | "failure" - } - - @Override - boolean hasHandlerSpan(ServerEndpoint endpoint) { - true - } - - @Override - boolean testNotFound() { - false - } - - @Override - boolean testPathParam() { - true - } - - boolean testInterfaceMethodWithPath() { - true - } - - boolean asyncCancelHasSendError() { - false - } - - boolean shouldTestCompletableStageAsync() { - Boolean.getBoolean("testLatestDeps") - } - - @Override - boolean hasResponseCustomizer(ServerEndpoint endpoint) { - true - } - - @Override - void serverSpan(TraceAssert trace, - int index, - String traceID = null, - String parentID = null, - String method = "GET", - ServerEndpoint endpoint = SUCCESS, - String spanID = null) { - serverSpan(trace, index, traceID, parentID, spanID, method, - endpoint == PATH_PARAM ? getContextPath() + "/path/{id}/param" : endpoint.resolvePath(address).path, - endpoint.resolve(address), - endpoint.status, - endpoint.query) - } - - void asyncServerSpan(TraceAssert trace, - int index, - String url, - int statusCode) { - def rawUrl = URI.create(url).toURL() - serverSpan(trace, index, null, null, null, "GET", - rawUrl.path, - rawUrl.toURI(), - statusCode, - null) - } - - void serverSpan(TraceAssert trace, - int index, - String traceID, - String parentID, - String spanID, - String method, - String path, - URI fullUrl, - int statusCode, - String query) { - trace.span(index) { - name method + " " + path - kind SERVER - if (statusCode >= 500) { - status ERROR - } - if (traceID != null) { - traceId traceID - } - if (parentID != null) { - parentSpanId parentID - } else { - hasNoParent() - } - if (spanID != null) { - spanId spanID - } - attributes { - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" fullUrl.host - "$ServerAttributes.SERVER_PORT" fullUrl.port - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$UrlAttributes.URL_SCHEME" fullUrl.getScheme() - "$UrlAttributes.URL_PATH" fullUrl.getPath() - "$UrlAttributes.URL_QUERY" fullUrl.getQuery() - "$HttpAttributes.HTTP_REQUEST_METHOD" method - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" statusCode - "$UserAgentAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT - "$ClientAttributes.CLIENT_ADDRESS" TEST_CLIENT_IP - // Optional - "$HttpAttributes.HTTP_ROUTE" path - if (fullUrl.getPath().endsWith(ServerEndpoint.CAPTURE_HEADERS.getPath())) { - "http.request.header.x-test-request" { it == ["test"] } - "http.response.header.x-test-response" { it == ["test"] } - } - if (statusCode >= 500) { - "$ErrorAttributes.ERROR_TYPE" "$statusCode" - } - } - } - } - - @Override - void handlerSpan(TraceAssert trace, - int index, - Object parent, - String method = "GET", - ServerEndpoint endpoint = SUCCESS) { - handlerSpan(trace, index, parent, - endpoint.name().toLowerCase(), - false, - endpoint == EXCEPTION, - EXCEPTION.body) - } - - void handlerSpan(TraceAssert trace, - int index, - Object parent, - String methodName, - boolean isCancelled, - boolean isError, - String exceptionMessage = null) { - trace.span(index) { - name "JaxRsTestResource.${methodName}" - kind INTERNAL - if (isError) { - status ERROR - errorEvent(Exception, exceptionMessage) - } - childOf((SpanData) parent) - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" "test.JaxRsTestResource" - "$CodeIncubatingAttributes.CODE_FUNCTION" methodName - if (isCancelled) { - "jaxrs.canceled" true - } - } - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsFilterTest.java b/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsFilterTest.java new file mode 100644 index 000000000000..29ea6e04aa5c --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsFilterTest.java @@ -0,0 +1,189 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_ROUTE; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.sdk.trace.data.StatusData; +import java.util.stream.Stream; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public abstract class AbstractJaxRsFilterTest extends AbstractHttpServerUsingTest { + + protected static class TestResponse { + private final String text; + private final int status; + + public TestResponse(String text, int status) { + this.text = text; + this.status = status; + } + } + + protected abstract TestResponse makeRequest(String url) throws Exception; + + private TestResponse runRequest(String resource) throws Exception { + if (runsOnServer()) { + return makeRequest(resource); + } + // start a trace because the test doesn't go through any servlet or other instrumentation. + return testing().runWithHttpServerSpan(() -> makeRequest(resource)); + } + + protected boolean testAbortPrematch() { + return true; + } + + protected boolean runsOnServer() { + return false; + } + + protected String defaultServerRoute() { + return null; + } + + protected abstract void setAbortStatus(boolean abortNormal, boolean abortPrematch); + + static Stream requests() { + return Stream.of( + Arguments.of( + "/test/hello/bob", false, false, "/test/hello/{name}", "Test1.hello", "Test1 bob!"), + Arguments.of( + "/test2/hello/bob", false, false, "/test2/hello/{name}", "Test2.hello", "Test2 bob!"), + Arguments.of( + "/test3/hi/bob", false, false, "/test3/hi/{name}", "Test3.hello", "Test3 bob!"), + // Resteasy and Jersey give different resource class names for just the below case + // Resteasy returns "SubResource.class" + // Jersey returns "Test1.class + // Arguments.of("/test/hello/bob", true, false, "/test/hello/{name}", "Test1.hello", + // "Aborted"), + Arguments.of( + "/test2/hello/bob", true, false, "/test2/hello/{name}", "Test2.hello", "Aborted"), + Arguments.of("/test3/hi/bob", true, false, "/test3/hi/{name}", "Test3.hello", "Aborted"), + Arguments.of( + "/test/hello/bob", + false, + true, + null, + "PrematchRequestFilter.filter", + "Aborted Prematch"), + Arguments.of( + "/test2/hello/bob", + false, + true, + null, + "PrematchRequestFilter.filter", + "Aborted Prematch"), + Arguments.of( + "/test3/hi/bob", + false, + true, + null, + "PrematchRequestFilter.filter", + "Aborted Prematch")); + } + + @ParameterizedTest + @MethodSource("requests") + void request( + String resource, + boolean abortNormal, + boolean abortPrematch, + String route, + String controllerName, + String expectedResponse) + throws Exception { + Assumptions.assumeTrue(!abortPrematch || testAbortPrematch()); + + setAbortStatus(abortNormal, abortPrematch); + boolean abort = abortNormal || abortPrematch; + + TestResponse response = runRequest(resource); + assertThat(response.text).isEqualTo(expectedResponse); + + assertThat(response.status) + .isEqualTo( + abort + ? 401 // Response.Status.UNAUTHORIZED.statusCode + : 200); // Response.Status.OK.statusCode + + String serverRoute = route != null ? route : defaultServerRoute(); + String method = runsOnServer() ? "POST" : "GET"; + String expectedServerSpanName = serverRoute == null ? method : method + " " + serverRoute; + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> { + span.hasName(expectedServerSpanName).hasKind(SpanKind.SERVER); + if (runsOnServer() && abortNormal) { + span.hasStatus(StatusData.unset()); + } + }, + span -> { + span.hasName(controllerName).hasParent(trace.getSpan(0)); + if (abortPrematch) { + span.hasAttributesSatisfyingExactly( + satisfies( + CODE_NAMESPACE, + name -> name.endsWith("JaxRsFilterTest$PrematchRequestFilter")), + equalTo(CODE_FUNCTION, "filter")); + } else { + span.hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, name -> name.contains("Resource$Test")), + equalTo(CODE_FUNCTION, "hello")); + } + })); + } + + @Test + void nestedCall() throws Exception { + setAbortStatus(false, false); + + TestResponse response = runRequest("/test3/nested"); + assertThat(response.status).isEqualTo(200); // Response.Status.OK.statusCode + assertThat(response.text).isEqualTo("Test3 nested!"); + + String method = runsOnServer() ? "POST" : "GET"; + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> { + span.hasName(method + " /test3/nested") + .hasKind(SpanKind.SERVER) + .hasNoParent(); + if (!runsOnServer()) { + span.hasAttributesSatisfyingExactly( + equalTo(HTTP_REQUEST_METHOD, method), + equalTo(HTTP_ROUTE, "/test3/nested"), + equalTo(ERROR_TYPE, HttpConstants._OTHER)); + } + }, + span -> + span.hasName("Test3.nested") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, name -> name.contains("Resource$Test")), + equalTo(CODE_FUNCTION, "nested")))); + } +} diff --git a/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsHttpServerTest.java b/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsHttpServerTest.java new file mode 100644 index 000000000000..9284c0a19339 --- /dev/null +++ b/instrumentation/jaxrs/jaxrs-common/testing/src/main/java/io/opentelemetry/instrumentation/jaxrs/AbstractJaxRsHttpServerTest.java @@ -0,0 +1,324 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jaxrs; + +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +public abstract class AbstractJaxRsHttpServerTest extends AbstractHttpServerTest { + + protected abstract void awaitBarrier(int amount, TimeUnit timeUnit) throws Exception; + + protected boolean testInterfaceMethodWithPath() { + return true; + } + + protected boolean asyncCancelHasSendError() { + return false; + } + + protected boolean shouldTestCompletableStageAsync() { + return Boolean.getBoolean("testLatestDeps"); + } + + @Override + protected void configure(HttpServerTestOptions options) { + super.configure(options); + + options.setHasHandlerSpan(endpoint -> true); + options.setTestNotFound(false); + options.setHasResponseCustomizer(endpoint -> true); + } + + @Test + void superMethodWithoutPathAnnotation() { + AggregatedHttpResponse response = + client.get(address.resolve("test-resource-super").toString()).aggregate().join(); + + assertThat(response.status().code()).isEqualTo(SUCCESS.getStatus()); + assertThat(response.contentUtf8()).isEqualTo(SUCCESS.getBody()); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + getContextPath() + "/test-resource-super") + .hasKind(SpanKind.SERVER) + .hasNoParent(), + span -> + span.hasName("controller") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + void interfaceMethodWithPathAnnotation() { + assumeTrue(testInterfaceMethodWithPath()); + + AggregatedHttpResponse response = + client.get(address.resolve("test-resource-interface/call").toString()).aggregate().join(); + + assertThat(response.status().code()).isEqualTo(SUCCESS.getStatus()); + assertThat(response.contentUtf8()).isEqualTo(SUCCESS.getBody()); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + getContextPath() + "/test-resource-interface/call") + .hasKind(SpanKind.SERVER) + .hasNoParent(), + span -> + span.hasName("controller") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + void subResourceLocator() { + AggregatedHttpResponse response = + client + .get(address.resolve("test-sub-resource-locator/call/sub").toString()) + .aggregate() + .join(); + + assertThat(response.status().code()).isEqualTo(SUCCESS.getStatus()); + assertThat(response.contentUtf8()).isEqualTo(SUCCESS.getBody()); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName( + "GET " + getContextPath() + "/test-sub-resource-locator/call/sub") + .hasKind(SpanKind.SERVER) + .hasNoParent(), + span -> + span.hasName("JaxRsSubResourceLocatorTestResource.call") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName("controller") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(1)), + span -> + span.hasName("SubResource.call") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName("controller") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(3)))); + } + + enum AsyncResponseTestKind { + SUCCESSFUL("succeed", 200) { + @Override + void assertBody(String body) { + assertThat(body).isEqualTo("success"); + } + }, + FAILING("throw", 500) { + @Override + void assertBody(String body) { + assertThat(body).isEqualTo("failure"); + } + }, + CANCELED("cancel", 503) { + @Override + void assertBody(String body) { + assertThat(body).isNotNull(); + } + }; + + final String action; + final int statusCode; + + AsyncResponseTestKind(String action, int statusCode) { + this.action = action; + this.statusCode = statusCode; + } + + abstract void assertBody(String body); + } + + @ParameterizedTest + @EnumSource(AsyncResponseTestKind.class) + void shouldHandleAsyncResponse(AsyncResponseTestKind testKind) throws Exception { + String url = address.resolve("async?action=" + testKind.action).toString(); + CompletableFuture futureResponse = client.get(url).aggregate(); + + // there are no traces yet + assertThat(testing().getExportedSpans()).isEmpty(); + + // barrier is released and resource class sends response + awaitBarrier(10, SECONDS); + + AggregatedHttpResponse response = futureResponse.join(); + + assertThat(response.status().code()).isEqualTo(testKind.statusCode); + testKind.assertBody(response.contentUtf8()); + + testing() + .waitAndAssertTraces( + trace -> { + List> assertions = + new ArrayList<>( + Arrays.asList( + span -> + assertServerSpan( + span, + "GET", + new ServerEndpoint( + "async", + "async?action=" + testKind.action, + testKind.statusCode, + null, + false), + testKind.statusCode), + span -> { + span.hasName("JaxRsTestResource.asyncOp") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + satisfies( + CODE_NAMESPACE, name -> name.endsWith("JaxRsTestResource")), + equalTo(CODE_FUNCTION, "asyncOp"), + equalTo( + AttributeKey.booleanKey("jaxrs.canceled"), + testKind == AsyncResponseTestKind.CANCELED ? true : null)); + if (testKind == AsyncResponseTestKind.FAILING) { + span.hasStatus(StatusData.error()) + .hasException(new IllegalStateException("failure")); + } + })); + if (asyncCancelHasSendError() && testKind == AsyncResponseTestKind.CANCELED) { + assertions.add( + span -> + span.satisfies( + spanData -> assertThat(spanData.getName()).endsWith("sendError")) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(1))); + } + trace.hasSpansSatisfyingExactly(assertions); + }); + } + + enum CompletionStageTestKind { + SUCCESSFUL("succeed", 200) { + @Override + void assertBody(String body) { + assertThat(body).isEqualTo("success"); + } + }, + FAILING("throw", 500) { + @Override + void assertBody(String body) { + assertThat(body).isEqualTo("failure"); + } + }; + + final String action; + final int statusCode; + + CompletionStageTestKind(String action, int statusCode) { + this.action = action; + this.statusCode = statusCode; + } + + abstract void assertBody(String body); + } + + @ParameterizedTest + @EnumSource(CompletionStageTestKind.class) + void shouldHandleCompletionStage(CompletionStageTestKind testKind) throws Exception { + // JAX-RS 2.1+ only + assumeTrue(shouldTestCompletableStageAsync()); + + String url = address.resolve("async-completion-stage?action=" + testKind.action).toString(); + CompletableFuture futureResponse = client.get(url).aggregate(); + + // there are no traces yet + assertThat(testing().getExportedSpans()).isEmpty(); + + // barrier is released and resource class sends response + awaitBarrier(10, SECONDS); + + AggregatedHttpResponse response = futureResponse.join(); + + assertThat(response.status().code()).isEqualTo(testKind.statusCode); + testKind.assertBody(response.contentUtf8()); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + assertServerSpan( + span, + "GET", + new ServerEndpoint( + "async", + "async-completion-stage?action=" + testKind.action, + testKind.statusCode, + null, + false), + testKind.statusCode), + span -> { + span.hasName("JaxRsTestResource.jaxRs21Async") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo( + CODE_NAMESPACE, + "io.opentelemetry.instrumentation.jaxrs.v2_0.test.JaxRsTestResource"), + equalTo(CODE_FUNCTION, "jaxRs21Async")); + if (testKind == CompletionStageTestKind.FAILING) { + span.hasStatus(StatusData.error()) + .hasException(new IllegalStateException("failure")); + } + })); + } + + @Override + protected SpanDataAssert assertHandlerSpan( + SpanDataAssert span, String method, ServerEndpoint endpoint) { + String methodName = endpoint.name().toLowerCase(Locale.ROOT); + return span.hasName("JaxRsTestResource." + methodName) + .hasKind(SpanKind.INTERNAL) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, name -> name.endsWith("JaxRsTestResource")), + equalTo(CODE_FUNCTION, methodName)); + } +}