Add serlvet filter test to spring-webmvc-6.0
RENAME
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/groovy/test/filter/FilteredAppConfig.groovy
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/groovy/test/filter/ServletFilterConfig.groovy
@@ -7,21 +7,8 @@ package test.filter
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
-import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Bean
-import org.springframework.http.HttpInputMessage
-import org.springframework.http.HttpOutputMessage
-import org.springframework.http.MediaType
-import org.springframework.http.converter.AbstractHttpMessageConverter
-import org.springframework.http.converter.HttpMessageConverter
-import org.springframework.http.converter.HttpMessageNotReadableException
-import org.springframework.http.converter.HttpMessageNotWritableException
-import org.springframework.util.StreamUtils
-import org.springframework.web.HttpMediaTypeNotAcceptableException
-import org.springframework.web.accept.ContentNegotiationStrategy
-import org.springframework.web.context.request.NativeWebRequest
-import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
+import org.springframework.context.annotation.Configuration
import javax.servlet.Filter
import javax.servlet.FilterChain
@@ -31,7 +18,6 @@ import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
-import java.nio.charset.StandardCharsets
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
@@ -42,43 +28,8 @@ import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
-@SpringBootApplication
-class FilteredAppConfig extends WebMvcConfigurerAdapter {
-
- @Override
- void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
- configurer.favorPathExtension(false)
- .favorParameter(true)
- .ignoreAcceptHeader(true)
- .useJaf(false)
- .defaultContentTypeStrategy(new ContentNegotiationStrategy() {
- @Override
- List<MediaType> resolveMediaTypes(NativeWebRequest webRequest) throws HttpMediaTypeNotAcceptableException {
- return [MediaType.TEXT_PLAIN]
- }
- })
- }
-
- @Bean
- HttpMessageConverter<Map<String, Object>> createPlainMapMessageConverter() {
- return new AbstractHttpMessageConverter<Map<String, Object>>(MediaType.TEXT_PLAIN) {
-
- @Override
- protected boolean supports(Class<?> clazz) {
- return Map.isAssignableFrom(clazz)
- }
-
- @Override
- protected Map<String, Object> readInternal(Class<? extends Map<String, Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
- return null
- }
-
- @Override
- protected void writeInternal(Map<String, Object> stringObjectMap, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
- StreamUtils.copy(stringObjectMap.get("message"), StandardCharsets.UTF_8, outputMessage.getBody())
- }
- }
- }
+@Configuration
+class ServletFilterConfig {
@Bean
Filter servletFilter() {

MODIFY
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/groovy/test/filter/ServletFilterTest.groovy
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/groovy/test/filter/ServletFilterTest.groovy
package test.filter
-
-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 org.springframework.boot.SpringApplication
-import org.springframework.context.ConfigurableApplicationContext
+import filter.AbstractServletFilterTest
import test.boot.SecurityConfig
-import static io.opentelemetry.api.trace.SpanKind.INTERNAL
-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.NOT_FOUND
-import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM
-import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
-import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
-
-class ServletFilterTest extends HttpServerTest<ConfigurableApplicationContext> implements AgentTestTrait {
-
- @Override
- ConfigurableApplicationContext startServer(int port) {
- def app = new SpringApplication(FilteredAppConfig, SecurityConfig)
- app.setDefaultProperties(["server.port": port, "server.error.include-message": "always"])
- def context = app.run()
- return context
- }
-
- @Override
- void stopServer(ConfigurableApplicationContext ctx) {
- ctx.close()
- }
-
- @Override
- boolean hasHandlerSpan(ServerEndpoint endpoint) {
- endpoint == NOT_FOUND
- }
-
- @Override
- boolean hasErrorPageSpans(ServerEndpoint endpoint) {
- endpoint == ERROR || endpoint == EXCEPTION || endpoint == NOT_FOUND
- }
+class ServletFilterTest extends AbstractServletFilterTest {
- @Override
- boolean hasResponseSpan(ServerEndpoint endpoint) {
- endpoint == REDIRECT || endpoint == ERROR || endpoint == NOT_FOUND
+ Class<?> securityConfigClass() {
+ SecurityConfig
}
- @Override
- void responseSpan(TraceAssert trace, int index, Object parent, String method, ServerEndpoint endpoint) {
- switch (endpoint) {
- case REDIRECT:
- redirectSpan(trace, index, parent)
- break
- case ERROR:
- case NOT_FOUND:
- sendErrorSpan(trace, index, parent)
- break
- }
- }
-
- @Override
- boolean testPathParam() {
- true
- }
-
- @Override
- void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint) {
- trace.span(index) {
- name "ResourceHttpRequestHandler.handleRequest"
- kind INTERNAL
- childOf((SpanData) parent)
- }
- }
-
- @Override
- String expectedHttpRoute(ServerEndpoint endpoint) {
- switch (endpoint) {
- case PATH_PARAM:
- return getContextPath() + "/path/{id}/param"
- case NOT_FOUND:
- return getContextPath() + "/**"
- default:
- return super.expectedHttpRoute(endpoint)
- }
- }
-
- @Override
- void errorPageSpans(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) {
- trace.span(index) {
- name "BasicErrorController.error"
- kind INTERNAL
- childOf((SpanData) parent)
- attributes {
- }
- }
+ Class<?> filterConfigClass() {
+ ServletFilterConfig
}
}

ADD
instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterConfig.groovy
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import io.opentelemetry.instrumentation.test.base.HttpServerTest
+import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+
+import jakarta.servlet.Filter
+import jakarta.servlet.FilterChain
+import jakarta.servlet.FilterConfig
+import jakarta.servlet.ServletException
+import jakarta.servlet.ServletRequest
+import jakarta.servlet.ServletResponse
+import jakarta.servlet.http.HttpServletRequest
+import jakarta.servlet.http.HttpServletResponse
+
+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
+
+@Configuration
+class ServletFilterConfig {
+
+ @Bean
+ Filter servletFilter() {
+ return new Filter() {
+
+ @Override
+ void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest req = (HttpServletRequest) request
+ HttpServletResponse resp = (HttpServletResponse) response
+ ServerEndpoint endpoint = ServerEndpoint.forPath(req.servletPath)
+ HttpServerTest.controller(endpoint) {
+ resp.contentType = "text/plain"
+ switch (endpoint) {
+ case SUCCESS:
+ resp.status = endpoint.status
+ resp.writer.print(endpoint.body)
+ break
+ case QUERY_PARAM:
+ resp.status = endpoint.status
+ resp.writer.print(req.queryString)
+ break
+ case PATH_PARAM:
+ resp.status = endpoint.status
+ resp.writer.print(endpoint.body)
+ break
+ case REDIRECT:
+ resp.sendRedirect(endpoint.body)
+ break
+ case CAPTURE_HEADERS:
+ resp.setHeader("X-Test-Response", req.getHeader("X-Test-Request"))
+ resp.status = endpoint.status
+ resp.writer.print(endpoint.body)
+ break
+ case ERROR:
+ resp.sendError(endpoint.status, endpoint.body)
+ break
+ case EXCEPTION:
+ throw new Exception(endpoint.body)
+ case INDEXED_CHILD:
+ INDEXED_CHILD.collectSpanAttributes { name -> req.getParameter(name) }
+ resp.writer.print(endpoint.body)
+ break
+ default:
+ chain.doFilter(request, response)
+ }
+ }
+ }
+
+ @Override
+ void destroy() {
+ }
+ }
+ }
+}

ADD
instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterTest.groovy
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import filter.AbstractServletFilterTest
+
+class ServletFilterTest extends AbstractServletFilterTest {
+
+ Class<?> securityConfigClass() {
+ SecurityConfig
+ }
+
+ Class<?> filterConfigClass() {
+ ServletFilterConfig
+ }
+}

ADD
instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/groovy/filter/AbstractServletFilterTest.groovy
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package filter
+
+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 org.springframework.boot.SpringApplication
+import org.springframework.context.ConfigurableApplicationContext
+
+import static io.opentelemetry.api.trace.SpanKind.INTERNAL
+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.NOT_FOUND
+import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM
+import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
+import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
+
+abstract class AbstractServletFilterTest extends HttpServerTest<ConfigurableApplicationContext> implements AgentTestTrait {
+
+ abstract Class<?> securityConfigClass()
+
+ abstract Class<?> filterConfigClass()
+
+ @Override
+ ConfigurableApplicationContext startServer(int port) {
+ def app = new SpringApplication(FilteredAppConfig, securityConfigClass(), filterConfigClass())
+ app.setDefaultProperties(["server.port": port, "server.error.include-message": "always"])
+ def context = app.run()
+ return context
+ }
+
+ @Override
+ void stopServer(ConfigurableApplicationContext ctx) {
+ ctx.close()
+ }
+
+ @Override
+ boolean hasHandlerSpan(ServerEndpoint endpoint) {
+ endpoint == NOT_FOUND
+ }
+
+ @Override
+ boolean hasErrorPageSpans(ServerEndpoint endpoint) {
+ endpoint == ERROR || endpoint == EXCEPTION || endpoint == NOT_FOUND
+ }
+
+ @Override
+ boolean hasResponseSpan(ServerEndpoint endpoint) {
+ endpoint == REDIRECT || endpoint == ERROR || endpoint == NOT_FOUND
+ }
+
+ @Override
+ void responseSpan(TraceAssert trace, int index, Object parent, String method, ServerEndpoint endpoint) {
+ switch (endpoint) {
+ case REDIRECT:
+ redirectSpan(trace, index, parent)
+ break
+ case ERROR:
+ case NOT_FOUND:
+ sendErrorSpan(trace, index, parent)
+ break
+ }
+ }
+
+ @Override
+ boolean testPathParam() {
+ true
+ }
+
+ @Override
+ void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint) {
+ trace.span(index) {
+ name "ResourceHttpRequestHandler.handleRequest"
+ kind INTERNAL
+ childOf((SpanData) parent)
+ }
+ }
+
+ @Override
+ String expectedHttpRoute(ServerEndpoint endpoint) {
+ switch (endpoint) {
+ case PATH_PARAM:
+ return getContextPath() + "/path/{id}/param"
+ case NOT_FOUND:
+ return getContextPath() + "/**"
+ default:
+ return super.expectedHttpRoute(endpoint)
+ }
+ }
+
+ @Override
+ void errorPageSpans(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) {
+ trace.span(index) {
+ name "BasicErrorController.error"
+ kind INTERNAL
+ childOf((SpanData) parent)
+ attributes {
+ }
+ }
+ }
+}

ADD
instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/groovy/filter/FilteredAppConfig.groovy
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package filter
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.Bean
+import org.springframework.format.FormatterRegistry
+import org.springframework.http.HttpInputMessage
+import org.springframework.http.HttpOutputMessage
+import org.springframework.http.MediaType
+import org.springframework.http.converter.AbstractHttpMessageConverter
+import org.springframework.http.converter.HttpMessageConverter
+import org.springframework.http.converter.HttpMessageNotReadableException
+import org.springframework.http.converter.HttpMessageNotWritableException
+import org.springframework.util.StreamUtils
+import org.springframework.validation.MessageCodesResolver
+import org.springframework.validation.Validator
+import org.springframework.web.HttpMediaTypeNotAcceptableException
+import org.springframework.web.accept.ContentNegotiationStrategy
+import org.springframework.web.context.request.NativeWebRequest
+import org.springframework.web.method.support.HandlerMethodArgumentResolver
+import org.springframework.web.method.support.HandlerMethodReturnValueHandler
+import org.springframework.web.servlet.HandlerExceptionResolver
+import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer
+import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer
+import org.springframework.web.servlet.config.annotation.CorsRegistry
+import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry
+import org.springframework.web.servlet.config.annotation.ViewResolverRegistry
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
+
+import java.nio.charset.StandardCharsets
+
+@SpringBootApplication
+class FilteredAppConfig implements WebMvcConfigurer {
+
+ @Override
+ void configurePathMatch(PathMatchConfigurer configurer) {}
+
+ @Override
+ void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
+ configurer.favorPathExtension(false)
+ .favorParameter(true)
+ .ignoreAcceptHeader(true)
+ .useJaf(false)
+ .defaultContentTypeStrategy(new ContentNegotiationStrategy() {
+ @Override
+ List<MediaType> resolveMediaTypes(NativeWebRequest webRequest) throws HttpMediaTypeNotAcceptableException {
+ return [MediaType.TEXT_PLAIN]
+ }
+ })
+ }
+
+ @Override
+ void configureAsyncSupport(AsyncSupportConfigurer configurer) {}
+
+ @Override
+ void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}
+
+ @Override
+ void addFormatters(FormatterRegistry registry) {}
+
+ @Override
+ void addInterceptors(InterceptorRegistry registry) {}
+
+ @Override
+ void addResourceHandlers(ResourceHandlerRegistry registry) {}
+
+ @Override
+ void addCorsMappings(CorsRegistry registry) {}
+
+ @Override
+ void addViewControllers(ViewControllerRegistry registry) {}
+
+ @Override
+ void configureViewResolvers(ViewResolverRegistry registry) {}
+
+ @Override
+ void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {}
+
+ @Override
+ void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {}
+
+ @Override
+ void configureMessageConverters(List<HttpMessageConverter<?>> converters) {}
+
+ @Override
+ void extendMessageConverters(List<HttpMessageConverter<?>> converters) {}
+
+ @Override
+ void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {}
+
+ @Override
+ void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {}
+
+ @Override
+ Validator getValidator() {
+ return null
+ }
+
+ @Override
+ MessageCodesResolver getMessageCodesResolver() {
+ return null
+ }
+
+ @Bean
+ HttpMessageConverter<Map<String, Object>> createPlainMapMessageConverter() {
+ return new AbstractHttpMessageConverter<Map<String, Object>>(MediaType.TEXT_PLAIN) {
+
+ @Override
+ protected boolean supports(Class<?> clazz) {
+ return Map.isAssignableFrom(clazz)
+ }
+
+ @Override
+ protected Map<String, Object> readInternal(Class<? extends Map<String, Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
+ return null
+ }
+
+ @Override
+ protected void writeInternal(Map<String, Object> stringObjectMap, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
+ StreamUtils.copy(stringObjectMap.get("message") as String, StandardCharsets.UTF_8, outputMessage.getBody())
+ }
+ }
+ }
+}

RENAME
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/test/groovy/test/filter/TestController.groovy
instrumentation/spring/spring-webmvc/spring-webmvc-common/testing/src/main/groovy/filter/TestController.groovy
* SPDX-License-Identifier: Apache-2.0
*/
-package test.filter
+package filter
import org.springframework.http.HttpStatus

Add serlvet filter test to spring-webmvc-6.0 (#7406)