From 713ff1c865f80e5863c28650791cd25c8fd22df0 Mon Sep 17 00:00:00 2001 From: Denis Stepanov Date: Thu, 29 Aug 2024 08:40:12 +0200 Subject: [PATCH] Fix issue with root routing + improve tests (#11123) --- .../PleaseEnableRoutesBySpecNameSpec.groovy | 18 ++++ .../docs/writable/TemplateController.java | 2 + .../docs/writable/WritableSpec.groovy | 3 +- .../server/netty/ConnectionCloseSpec.groovy | 2 + .../server/netty/NettyMultiServerSpec.groovy | 6 +- .../netty/RequestCertificateSpec.groovy | 2 + .../netty/TestNettySecondaryServer.java | 5 +- .../netty/binding/CookieBindingSpec.groovy | 3 + .../binding/CustomParameterBindingSpec.groovy | 2 + .../netty/binding/HeaderBindingSpec.groovy | 2 + .../netty/binding/HttpResponseSpec.groovy | 80 +++++++++++++++++ .../netty/binding/NettyHttpServerSpec.groovy | 62 +++++++------ .../netty/binding/ParameterBindingSpec.groovy | 2 + .../QueryParameterFormattingSpec.groovy | 3 +- .../configuration/MaxHeaderSizeSpec.groovy | 3 + .../consumes/ContentTypeHeaderSpec.groovy | 5 +- .../context/ServerRequestContextSpec.groovy | 7 +- .../server/netty/cors/CorsFilterSpec.groovy | 4 +- .../errors/HttpStatusExceptionSpec.groovy | 2 + .../netty/filters/FilterBodySpec.groovy | 1 + .../netty/filters/FilterErrorSpec.groovy | 13 +-- .../netty/http2/Http2Java11ClientSpec.groovy | 10 ++- .../server/netty/http2/Http2PostTest.java | 2 + .../netty/interceptor/ContextPathFilter.java | 2 + .../server/netty/interceptor/FirstFilter.java | 2 + .../HttpFilterContextPathSpec.groovy | 2 +- .../netty/interceptor/HttpFilterSpec.groovy | 1 + .../netty/interceptor/SecondFilter.java | 2 + .../netty/interceptor/SecureController.java | 2 + .../netty/interceptor/TestReactiveFilter.java | 2 + .../netty/interceptor/TestSecurityFilter.java | 2 + .../netty/java/ParameterController.java | 2 + .../server/netty/java/ResponseController.java | 2 + .../LinuxNativeTransportSpec.groovy | 2 +- .../MacNativeTransportSpec.groovy | 2 +- .../NativeTransportController.java | 2 + .../server/netty/redirect/RedirectSpec.groovy | 4 +- .../http/server/netty/routing/KeyValue.java | 26 ++++++ .../http/server/netty/routing/MyClient.java | 23 +++++ .../server/netty/routing/MyController.java | 37 ++++++++ .../server/netty/routing/RootRoutingTest.java | 23 +++++ .../ssl/DeprecatedSslConfigurationSpec.groovy | 4 + .../netty/stream/ErrorResponseSpec.groovy | 5 ++ .../server/netty/stream/FluxBodySpec.groovy | 4 +- .../netty/stream/FluxFullBodySpec.groovy | 21 ++++- .../threading/ThreadSelectionSpec.groovy | 16 ++-- .../websocket/BinaryChatClientWebSocket.java | 2 + .../websocket/BinaryChatServerWebSocket.java | 2 + .../websocket/BinaryWebSocketSpec.groovy | 18 ++-- .../netty/websocket/ChatClientWebSocket.java | 2 + .../netty/websocket/ChatServerWebSocket.java | 2 + .../netty/websocket/ColludingController.java | 2 + .../websocket/PojoChatClientWebSocket.java | 5 +- .../netty/websocket/PojoWebSocketSpec.groovy | 2 +- .../websocket/QueryParamServerWebSocket.java | 2 + .../ReactivePojoChatServerWebSocket.java | 2 + .../websocket/SimpleTextWebSocketSpec.groovy | 9 +- .../websocket/WebSocketErrorsSpec.groovy | 7 +- .../netty/websocket/errors/ErrorsClient.java | 2 + .../websocket/errors/MessageErrorSocket.java | 2 + .../errors/MessageErrorSocketWithOnError.java | 2 + .../websocket/errors/TimeoutErrorSocket.java | 3 +- ...orServiceWithMultipleEventLoopsSpec.groovy | 4 + .../http/scope/RequestScopeSpec.groovy | 9 ++ .../tck/tests/routing/RootRoutingTest.java | 86 +++++++++++++++++++ .../http/uri/UriTemplateMatcher.java | 9 +- 66 files changed, 514 insertions(+), 85 deletions(-) create mode 100644 http-server-netty/src/test/groovy/io/micronaut/PleaseEnableRoutesBySpecNameSpec.groovy create mode 100644 http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/KeyValue.java create mode 100644 http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyClient.java create mode 100644 http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyController.java create mode 100644 http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/RootRoutingTest.java create mode 100644 http-server-tck/src/main/java/io/micronaut/http/server/tck/tests/routing/RootRoutingTest.java diff --git a/http-server-netty/src/test/groovy/io/micronaut/PleaseEnableRoutesBySpecNameSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/PleaseEnableRoutesBySpecNameSpec.groovy new file mode 100644 index 00000000000..418e3a026ca --- /dev/null +++ b/http-server-netty/src/test/groovy/io/micronaut/PleaseEnableRoutesBySpecNameSpec.groovy @@ -0,0 +1,18 @@ +package io.micronaut + +import io.micronaut.http.server.netty.AbstractMicronautSpec +import io.micronaut.web.router.Router + +class PleaseEnableRoutesBySpecNameSpec extends AbstractMicronautSpec { + + void "don't add more public routes in test"() { + // A lot of activate routes, filters etc. complicates debugging + // Please use @Requires(property="spec.name.. to enable your route and filters only for particular tests + given: + Router router = applicationContext.getBean(Router) + expect: + router.uriRoutes().toList().size() == 0 + } + + +} diff --git a/http-server-netty/src/test/groovy/io/micronaut/docs/writable/TemplateController.java b/http-server-netty/src/test/groovy/io/micronaut/docs/writable/TemplateController.java index 7236397280c..8f9c894d45d 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/docs/writable/TemplateController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/docs/writable/TemplateController.java @@ -19,6 +19,7 @@ import groovy.text.SimpleTemplateEngine; import groovy.text.Template; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.io.Writable; import io.micronaut.core.util.CollectionUtils; import io.micronaut.http.MediaType; @@ -28,6 +29,7 @@ //end::imports[] //tag::clazz[] +@Requires(property = "spec.name", value = "WritableSpec") @Controller("/template") public class TemplateController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/docs/writable/WritableSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/docs/writable/WritableSpec.groovy index 0d7a675134a..6b398789ea3 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/docs/writable/WritableSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/docs/writable/WritableSpec.groovy @@ -26,10 +26,9 @@ import spock.lang.Specification class WritableSpec extends Specification { - @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'WritableSpec']) @Shared @AutoCleanup HttpClient client = embeddedServer.getApplicationContext().createBean(HttpClient, embeddedServer.getURL()) - void "test render template"() { expect: HttpResponse resp = client.toBlocking().exchange('/template/welcome', String) diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ConnectionCloseSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ConnectionCloseSpec.groovy index 1fa75bdf3f7..4201639f966 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ConnectionCloseSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ConnectionCloseSpec.groovy @@ -1,6 +1,7 @@ package io.micronaut.http.server.netty import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpHeaders import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse @@ -86,6 +87,7 @@ class ConnectionCloseSpec extends Specification { server.close() } + @Requires(property = 'spec.name', value = 'ConnectionCloseSpec') @Controller("/connection") static class ConnectionCloseController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/NettyMultiServerSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/NettyMultiServerSpec.groovy index db8b39b8624..1ebb492ff07 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/NettyMultiServerSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/NettyMultiServerSpec.groovy @@ -1,8 +1,7 @@ package io.micronaut.http.server.netty - import io.micronaut.context.annotation.Property -import io.micronaut.core.util.StringUtils +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get @@ -17,7 +16,7 @@ import jakarta.inject.Named import spock.lang.Specification @MicronautTest -@Property(name = "NettyMultiServerSpec", value = StringUtils.TRUE) +@Property(name = "spec.name", value = "NettyMultiServerSpec") class NettyMultiServerSpec extends Specification { @Inject ApplicationConfiguration applicationConfiguration @@ -46,6 +45,7 @@ class NettyMultiServerSpec extends Specification { secondaryClient.close() } + @Requires(property = "spec.name", value = "NettyMultiServerSpec") @Controller("/test/secondary/server") static class TestController { @Get("/") diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/RequestCertificateSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/RequestCertificateSpec.groovy index 567df1e6c93..cb9f2ee7d73 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/RequestCertificateSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/RequestCertificateSpec.groovy @@ -1,5 +1,6 @@ package io.micronaut.http.server.netty +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest import io.micronaut.http.HttpStatus import io.micronaut.http.annotation.Controller @@ -71,6 +72,7 @@ class RequestCertificateSpec extends AbstractMicronautSpec { ] } + @Requires(property = 'spec.name', value = 'RequestCertificateSpec') @Controller static class TestController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/TestNettySecondaryServer.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/TestNettySecondaryServer.java index 77261ed522c..cba7527f53c 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/TestNettySecondaryServer.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/TestNettySecondaryServer.java @@ -3,21 +3,20 @@ import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; import io.micronaut.context.annotation.Requires; -import io.micronaut.core.util.StringUtils; import io.micronaut.http.server.netty.configuration.NettyHttpServerConfiguration; import io.micronaut.runtime.ApplicationConfiguration; import jakarta.inject.Inject; import jakarta.inject.Named; @Factory -@Requires(property = "NettyMultiServerSpec", value = StringUtils.TRUE) +@Requires(property = "spec.name", value = "NettyMultiServerSpec") public class TestNettySecondaryServer { @Inject ApplicationConfiguration applicationConfiguration; @Inject NettyEmbeddedServerFactory embeddedServerFactory; @Named("secondary") @Bean(preDestroy = "stop") - @Requires(property = "NettyMultiServerSpec", value = StringUtils.TRUE) + @Requires(property = "spec.name", value = "NettyMultiServerSpec") NettyEmbeddedServer secondaryServer() { NettyEmbeddedServer embeddedServer = embeddedServerFactory .build(new NettyHttpServerConfiguration(applicationConfiguration)); diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CookieBindingSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CookieBindingSpec.groovy index cff25946d3f..cdb5722a328 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CookieBindingSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CookieBindingSpec.groovy @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.binding +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.CookieValue @@ -69,10 +70,12 @@ class CookieBindingSpec extends AbstractMicronautSpec { result == "Cookie Value: foo" } + @Requires(property = "spec.name", value = "CookieBindingSpec") @Client('/cookie') static interface CookieClient extends CookieApi { } + @Requires(property = "spec.name", value = "CookieBindingSpec") @Controller("/cookie") static class CookieController implements CookieApi { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CustomParameterBindingSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CustomParameterBindingSpec.groovy index be2c25c58eb..a444d3e135c 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CustomParameterBindingSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/CustomParameterBindingSpec.groovy @@ -1,5 +1,6 @@ package io.micronaut.http.server.netty.binding +import io.micronaut.context.annotation.Requires import io.micronaut.core.annotation.Introspected import io.micronaut.core.convert.format.Format import io.micronaut.http.* @@ -83,6 +84,7 @@ class CustomParameterBindingSpec extends AbstractMicronautSpec { response.getBody().get() == "Parameter Value: The Stand" } + @Requires(property = 'spec.name', value = 'CustomParameterBindingSpec') @Controller(value = "/parameter", produces = MediaType.TEXT_PLAIN) static class ParameterController { @CustomHttpMethod(method="REPORT") diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HeaderBindingSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HeaderBindingSpec.groovy index 6c4ece0196d..ed67cfa0926 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HeaderBindingSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HeaderBindingSpec.groovy @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.binding +import io.micronaut.context.annotation.Requires import io.micronaut.core.convert.format.Format import io.micronaut.http.HttpHeaders import io.micronaut.http.HttpRequest @@ -67,6 +68,7 @@ class HeaderBindingSpec extends AbstractMicronautSpec { '/header/with-value' | "Header: application/json" | ['Content-Type': 'application/json'] } + @Requires(property = 'spec.name', value = 'HeaderBindingSpec') @Controller("/header") static class HeaderController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy index b340acdb871..e5f74b90995 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/HttpResponseSpec.groovy @@ -18,9 +18,12 @@ package io.micronaut.http.server.netty.binding import io.micronaut.context.ApplicationContext import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpHeaders +import io.micronaut.http.HttpMessage +import io.micronaut.http.HttpMethod import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse import io.micronaut.http.HttpStatus +import io.micronaut.http.MediaType import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get import io.micronaut.http.client.HttpClient @@ -298,4 +301,81 @@ class HttpResponseSpec extends AbstractMicronautSpec { Map getConfiguration() { super.getConfiguration() << ['micronaut.server.date-header': false] } + + @Requires(property = 'spec.name', value = 'HttpResponseSpec') + @Controller("/java/response") + static class ResponseController { + + @Get("/disallow") + public HttpResponse disallow() { + return HttpResponse.notAllowed(HttpMethod.DELETE); + } + + @Get("/accepted") + public HttpResponse accepted() { + return HttpResponse.accepted(); + } + + @Get("/accepted-uri") + public HttpResponse acceptedUri() { + return HttpResponse.accepted(HttpResponse.uri("http://example.com")); + } + + @Get("/created-uri") + public HttpResponse createdUri() { + return HttpResponse.created(HttpResponse.uri("http://test.com")); + } + + @Get("/created-body") + public HttpResponse createdBody() { + return HttpResponse.created(new io.micronaut.http.server.netty.java.Foo("blah", 10)); + } + + @Get("/created-body-uri") + public HttpResponse createdBodyUri() { + return HttpResponse.created(new io.micronaut.http.server.netty.java.Foo("blah", 10), HttpResponse.uri("http://test.com")); + } + + @Get("/ok") + public HttpResponse ok() { + return HttpResponse.ok(); + } + + @Get(value = "/ok-with-body", produces = MediaType.TEXT_PLAIN) + public HttpResponse okWithBody() { + return HttpResponse.ok("some text"); + } + + @Get(value = "/error-with-body", produces = MediaType.TEXT_PLAIN) + public HttpResponse errorWithBody() { + return HttpResponse.serverError().body("some text"); + } + + @Get("/ok-with-body-object") + public HttpResponse okWithBodyObject() { + return HttpResponse.ok(new io.micronaut.http.server.netty.java.Foo("blah", 10)) + .headers((headers)-> + headers.contentType(MediaType.APPLICATION_JSON_TYPE) + ); + } + + @Get("/status") + public HttpMessage status() { + return HttpResponse.status(HttpStatus.MOVED_PERMANENTLY); + } + + @Get("/custom-headers") + public HttpResponse customHeaders() { + return HttpResponse.ok("abc").contentType("text/plain").contentLength(7); + } + + @Get("/optional-response/{empty}") + public Optional optionalResponse(Boolean empty) { + if (empty) { + return Optional.empty(); + } else { + return Optional.of(HttpResponse.ok()); + } + } + } } diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/NettyHttpServerSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/NettyHttpServerSpec.groovy index a6afb652531..51452336e38 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/NettyHttpServerSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/NettyHttpServerSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.binding import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource import io.micronaut.context.event.StartupEvent @@ -32,7 +33,6 @@ import io.micronaut.http.client.DefaultHttpClientConfiguration import io.micronaut.http.client.HttpClient import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.http.server.exceptions.ServerStartupException -import io.micronaut.runtime.Micronaut import io.micronaut.runtime.event.annotation.EventListener import io.micronaut.runtime.server.EmbeddedServer import jakarta.inject.Singleton @@ -43,7 +43,6 @@ import spock.lang.Stepwise import java.time.Duration import java.time.temporal.ChronoUnit import java.util.concurrent.atomic.AtomicInteger - /** * @author Graeme Rocher * @since 1.0 @@ -54,9 +53,8 @@ class NettyHttpServerSpec extends Specification { void "test Micronaut server running"() { when: - ApplicationContext applicationContext = Micronaut.run() - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec']) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) HttpResponse response = client.toBlocking().exchange('/person/Fred', String) then: @@ -64,12 +62,12 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test run Micronaut server on same port as another server"() { when: - PropertySource propertySource = PropertySource.of('micronaut.server.port':-1) + PropertySource propertySource = PropertySource.of('micronaut.server.port':-1, 'spec.name': 'NettyHttpServerSpec') EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, propertySource, Environment.TEST) HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) @@ -80,7 +78,7 @@ class NettyHttpServerSpec extends Specification { when: "Run another server with same port" sleep(1_000) // wait for port to be not available - ApplicationContext.run(EmbeddedServer, PropertySource.of('micronaut.server.port':embeddedServer.getPort()), Environment.TEST) + ApplicationContext.run(EmbeddedServer, PropertySource.of('micronaut.server.port':embeddedServer.getPort(), 'spec.name': 'NettyHttpServerSpec'), Environment.TEST) then:"An error is thrown" def e = thrown(ServerStartupException) @@ -93,9 +91,8 @@ class NettyHttpServerSpec extends Specification { void "test Micronaut server running again"() { when: - ApplicationContext applicationContext = Micronaut.run() - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec']) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) HttpResponse response = client.toBlocking().exchange('/person/Fred', String) then: @@ -103,15 +100,14 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test Micronaut server on different port"() { when: int newPort = SocketUtils.findAvailableTcpPort() - ApplicationContext applicationContext = Micronaut.run('-port',newPort.toString()) - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec', 'micronaut.server.port':newPort.toString()]) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) HttpResponse response = client.toBlocking().exchange('/person/Fred', String) @@ -120,15 +116,14 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test bind method argument from request parameter"() { when: int newPort = SocketUtils.findAvailableTcpPort() - ApplicationContext applicationContext = Micronaut.run('-port',newPort.toString()) - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec', 'micronaut.server.port':newPort.toString()]) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) HttpResponse response = client.toBlocking().exchange('/person/another/job?id=10', String) @@ -137,15 +132,14 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test bind method argument from request parameter when parameter missing"() { when:"A required request parameter is missing" int newPort = SocketUtils.findAvailableTcpPort() - ApplicationContext applicationContext = Micronaut.run('-port',newPort.toString()) - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec', 'micronaut.server.port':newPort.toString()]) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) client.toBlocking().exchange('/person/another/job', String) @@ -155,15 +149,14 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test allowed methods handling"() { when:"A request is sent to the server for the wrong HTTP method" int newPort = SocketUtils.findAvailableTcpPort() - ApplicationContext applicationContext = Micronaut.run('-port',newPort.toString()) - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL()) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec', 'micronaut.server.port':newPort.toString()]) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) client.toBlocking().exchange(HttpRequest.POST('/person/job/test', '{}'), String) @@ -174,7 +167,7 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test expected connection persistence"() { @@ -184,9 +177,8 @@ class NettyHttpServerSpec extends Specification { config.connectionPoolConfiguration.enabled = true config.connectionPoolConfiguration.acquireTimeout = Duration.of(3, ChronoUnit.SECONDS); - ApplicationContext applicationContext = Micronaut.run() - EmbeddedServer embeddedServer = applicationContext.getBean(EmbeddedServer) - HttpClient client = applicationContext.createBean(HttpClient, embeddedServer.getURL(), config) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'NettyHttpServerSpec']) + HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL(), config) HttpRequest request = HttpRequest.create(HttpMethod.GET, '/person/Fred') HttpResponse response = client.toBlocking().exchange(request, String) @@ -196,12 +188,13 @@ class NettyHttpServerSpec extends Specification { cleanup: client.stop() - applicationContext.stop() + embeddedServer.stop() } void "test run Micronaut server when enabling both http and https"() { when: PropertySource propertySource = PropertySource.of( + 'spec.name': 'NettyHttpServerSpec', 'micronaut.server.port':httpPort, 'micronaut.server.ssl.enabled': true, 'micronaut.server.ssl.port': -1, @@ -232,6 +225,7 @@ class NettyHttpServerSpec extends Specification { def unsecurePort = SocketUtils.findAvailableTcpPort() when: PropertySource propertySource = PropertySource.of( + 'spec.name': 'NettyHttpServerSpec', 'micronaut.server.port': unsecurePort, 'micronaut.server.ssl.port': securePort, 'micronaut.server.ssl.enabled': true, @@ -252,6 +246,7 @@ class NettyHttpServerSpec extends Specification { void "test non dual protocol Micronaut server only fires startup event once"() { when: PropertySource propertySource = PropertySource.of( + 'spec.name': 'NettyHttpServerSpec', 'micronaut.server.port': SocketUtils.findAvailableTcpPort(), 'micronaut.server.dualProtocol':false ) @@ -268,6 +263,7 @@ class NettyHttpServerSpec extends Specification { void "test dual protocol only fires startup event once"() { when: PropertySource propertySource = PropertySource.of( + 'spec.name': 'NettyHttpServerSpec', 'micronaut.server.port': SocketUtils.findAvailableTcpPort(), 'micronaut.server.ssl.port': SocketUtils.findAvailableTcpPort(), 'micronaut.server.ssl.enabled': true, @@ -284,6 +280,7 @@ class NettyHttpServerSpec extends Specification { embeddedServer.applicationContext.stop() } + @Requires(property = "spec.name", value = "NettyHttpServerSpec") @Singleton static class EventCounter { AtomicInteger count = new AtomicInteger(0) @@ -294,6 +291,7 @@ class NettyHttpServerSpec extends Specification { } } + @Requires(property = "spec.name", value = "NettyHttpServerSpec") @Controller("/person") static class PersonController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/ParameterBindingSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/ParameterBindingSpec.groovy index d483f4ccb73..7c79c6f9c45 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/ParameterBindingSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/ParameterBindingSpec.groovy @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.binding +import io.micronaut.context.annotation.Requires import io.micronaut.core.annotation.Introspected import io.micronaut.core.convert.format.Format import io.micronaut.http.* @@ -107,6 +108,7 @@ class ParameterBindingSpec extends AbstractMicronautSpec { response.body().contains('Unexpected token (VALUE_STRING), expected END_ARRAY') } + @Requires(property = 'spec.name', value = 'ParameterBindingSpec') @Controller(value = "/parameter", produces = MediaType.TEXT_PLAIN) static class ParameterController { @Get diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/QueryParameterFormattingSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/QueryParameterFormattingSpec.groovy index 5b1f1700275..78706f1b671 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/QueryParameterFormattingSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/binding/QueryParameterFormattingSpec.groovy @@ -1,5 +1,6 @@ package io.micronaut.http.server.netty.binding +import io.micronaut.context.annotation.Requires import io.micronaut.core.annotation.Introspected import io.micronaut.core.convert.format.Format import io.micronaut.http.HttpMethod @@ -66,7 +67,7 @@ public class QueryParameterFormattingSpec extends AbstractMicronautSpec { var e = thrown(HttpClientResponseException) } - + @Requires(property = 'spec.name', value = 'QueryParameterFormattingSpec') @Controller(value = "/formatted", produces = MediaType.TEXT_PLAIN) static class FormattedController { @Get("csv") diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/configuration/MaxHeaderSizeSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/configuration/MaxHeaderSizeSpec.groovy index 033de6434c4..b175c66bbcf 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/configuration/MaxHeaderSizeSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/configuration/MaxHeaderSizeSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.configuration import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest import io.micronaut.http.HttpStatus import io.micronaut.http.annotation.Controller @@ -35,6 +36,7 @@ class MaxHeaderSizeSpec extends Specification { void "test that the max header size can be configured"() { given: EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [ + 'spec.name': 'MaxHeaderSizeSpec', 'micronaut.server.netty.maxHeaderSize':10 ]) HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL()) @@ -54,6 +56,7 @@ class MaxHeaderSizeSpec extends Specification { client.stop() } + @Requires(property = "spec.name", value = "MaxHeaderSizeSpec") @Controller('/max-header') static class TestController { @Get diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/consumes/ContentTypeHeaderSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/consumes/ContentTypeHeaderSpec.groovy index 75aca5114a5..ce1200fffc2 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/consumes/ContentTypeHeaderSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/consumes/ContentTypeHeaderSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.consumes import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.* import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get @@ -27,7 +28,7 @@ import spock.lang.Specification class ContentTypeHeaderSpec extends Specification { - @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ContentTypeHeaderSpec']) @Shared HttpClient client = embeddedServer.applicationContext.createBean( HttpClient, @@ -58,7 +59,7 @@ class ContentTypeHeaderSpec extends Specification { resp.body() == 'ok' } - + @Requires(property = "spec.name", value = "ContentTypeHeaderSpec") @Controller("/test/content-type") static class ContentTypeController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/context/ServerRequestContextSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/context/ServerRequestContextSpec.groovy index 32560932cf4..64fc8ecfdbf 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/context/ServerRequestContextSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/context/ServerRequestContextSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.context import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.core.propagation.PropagatedContext import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse @@ -53,7 +54,8 @@ class ServerRequestContextSpec extends Specification { EmbeddedServer, // limit number of threads to simulate thread sharing ['micronaut.executors.io.type': 'FIXED', - 'micronaut.executors.io.nThreads':'2',] + 'micronaut.executors.io.nThreads':'2', + 'spec.name': 'ServerRequestContextSpec'] ) @Unroll @@ -78,6 +80,7 @@ class ServerRequestContextSpec extends Specification { testClient.reactorContextStream() == '/test-context/reactor-context-stream' } + @Requires(property = 'spec.name', value = 'ServerRequestContextSpec') @Client('/test-context') @Consumes(MediaType.TEXT_PLAIN) static interface TestClient { @@ -104,6 +107,7 @@ class ServerRequestContextSpec extends Specification { String handlerError() } + @Requires(property = 'spec.name', value = 'ServerRequestContextSpec') @Controller('/test-context') @Produces(MediaType.TEXT_PLAIN) static class TestContextController { @@ -181,6 +185,7 @@ class ServerRequestContextSpec extends Specification { } } + @Requires(property = 'spec.name', value = 'ServerRequestContextSpec') @Singleton static class TestExceptionHandler implements ExceptionHandler> { @Inject diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/cors/CorsFilterSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/cors/CorsFilterSpec.groovy index d610c401c1a..a3e65433ee9 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/cors/CorsFilterSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/cors/CorsFilterSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.cors import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.core.annotation.Nullable import io.micronaut.core.util.StringUtils import io.micronaut.http.HttpAttributes @@ -55,7 +56,7 @@ class CorsFilterSpec extends Specification { @Shared @AutoCleanup - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'CorsFilterSpec']) void "non CORS request is passed through"() { given: @@ -537,6 +538,7 @@ class CorsFilterSpec extends Specification { HttpStatus.OK == response.status() } + @Requires(property = "spec.name", value = "CorsFilterSpec") @Controller static class TestController{ diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/errors/HttpStatusExceptionSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/errors/HttpStatusExceptionSpec.groovy index b6a02ec35bb..93d805de042 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/errors/HttpStatusExceptionSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/errors/HttpStatusExceptionSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.errors import groovy.json.JsonSlurper +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpHeaders import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse @@ -73,6 +74,7 @@ class HttpStatusExceptionSpec extends AbstractMicronautSpec { json.title == 'The title' } + @Requires(property = "spec.name", value = "HttpStatusExceptionSpec") @Controller('/errors') static class BookController { @Get diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterBodySpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterBodySpec.groovy index d8862ca935e..b0b7c45f1f2 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterBodySpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterBodySpec.groovy @@ -73,6 +73,7 @@ class FilterBodySpec extends Specification { } } + @Requires(property = 'spec.name', value = 'FilterBodySpec') @Controller("/filter-body") static class MyController { @Post("/delayed-body-controller") diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterErrorSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterErrorSpec.groovy index f1ddbe3625c..f8bb4e573b3 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterErrorSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/filters/FilterErrorSpec.groovy @@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicReference class FilterErrorSpec extends Specification { void "test errors emitted from filters interacting with exception handlers"() { - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': FilterErrorSpec.simpleName]) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['main.name': FilterErrorSpec.simpleName, 'spec.name': FilterErrorSpec.simpleName]) def ctx = server.applicationContext HttpClient client = ctx.createBean(HttpClient, server.getURL()) First first = ctx.getBean(First) @@ -78,7 +78,7 @@ class FilterErrorSpec extends Specification { } void "test non once per request filter throwing error does not loop"() { - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': FilterErrorSpec.simpleName + '2']) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['main.name': FilterErrorSpec.simpleName, 'spec.name': FilterErrorSpec.simpleName + '2']) def ctx = server.applicationContext HttpClient client = ctx.createBean(HttpClient, server.getURL()) FirstEvery filter = ctx.getBean(FirstEvery) @@ -104,7 +104,7 @@ class FilterErrorSpec extends Specification { } void "test non once per request filter throwing error directly does not loop"() { - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': FilterErrorSpec.simpleName + '2b']) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['main.name': FilterErrorSpec.simpleName, 'spec.name': FilterErrorSpec.simpleName + '2b']) def ctx = server.applicationContext HttpClient client = ctx.createBean(HttpClient, server.getURL()) @@ -128,7 +128,7 @@ class FilterErrorSpec extends Specification { } void "test filter throwing exception handled by exception handler throwing exception"() { - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': FilterErrorSpec.simpleName + '3']) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['main.name': FilterErrorSpec.simpleName, 'spec.name': FilterErrorSpec.simpleName + '3']) def ctx = server.applicationContext HttpClient client = ctx.createBean(HttpClient, server.getURL()) ExceptionException filter = ctx.getBean(ExceptionException) @@ -156,7 +156,7 @@ class FilterErrorSpec extends Specification { } void "test the error route is the route match"() { - EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': FilterErrorSpec.simpleName + '4']) + EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['main.name': FilterErrorSpec.simpleName, 'spec.name': FilterErrorSpec.simpleName + '4']) def ctx = server.applicationContext HttpClient client = ctx.createBean(HttpClient, server.getURL()) ExceptionRoute filter = ctx.getBean(ExceptionRoute) @@ -301,6 +301,7 @@ class FilterErrorSpec extends Specification { } } + @Requires(property = 'main.name', value = 'FilterErrorSpec') @Controller("/filter-error-spec") static class NeverReachedController { @@ -311,6 +312,7 @@ class FilterErrorSpec extends Specification { } + @Requires(property = 'main.name', value = 'FilterErrorSpec') @Controller("/filter-error-spec-3") static class HandledByHandlerController { @@ -321,6 +323,7 @@ class FilterErrorSpec extends Specification { } + @Requires(property = 'main.name', value = 'FilterErrorSpec') @Controller("/filter-error-spec-4") static class HandledByErrorRouteController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2Java11ClientSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2Java11ClientSpec.groovy index 8bcc6aff687..6f7ebfd81e6 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2Java11ClientSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2Java11ClientSpec.groovy @@ -1,12 +1,16 @@ package io.micronaut.http.server.netty.http2 import io.micronaut.context.annotation.Property -import io.micronaut.http.annotation.* +import io.micronaut.context.annotation.Requires +import io.micronaut.http.annotation.Body +import io.micronaut.http.annotation.Consumes +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Get +import io.micronaut.http.annotation.Put import io.micronaut.runtime.server.EmbeddedServer import io.micronaut.test.extensions.spock.annotation.MicronautTest import jakarta.inject.Inject import spock.lang.Issue -import spock.lang.Requires import spock.lang.Specification import javax.net.ssl.SSLContext @@ -23,6 +27,7 @@ import static java.time.Duration.ofSeconds import static java.util.concurrent.CompletableFuture.supplyAsync @MicronautTest +@Property(name = "spec.name", value = "Http2Java11ClientSpec") @Property(name = "micronaut.server.http-version", value = "2.0") @Property(name = "micronaut.server.ssl.enabled", value = "true") @Property(name = "micronaut.server.ssl.port", value = "-1") @@ -122,6 +127,7 @@ class Http2Java11ClientSpec extends Specification { return context } + @Requires(property = "spec.name", value = "Http2Java11ClientSpec") @Controller('/http2/java11') static class ExampleController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2PostTest.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2PostTest.java index 585af18118b..e6875f4358a 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2PostTest.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/http2/Http2PostTest.java @@ -35,6 +35,7 @@ import java.util.concurrent.TimeoutException; @MicronautTest +@Property(name = "spec.name", value = "Http2PostTest") @Property(name = "micronaut.server.http-version", value = "2.0") @Property(name = "micronaut.server.netty.log-level", value = "TRACE") @Property(name = "micronaut.http.client.log-level", value = "TRACE") @@ -131,6 +132,7 @@ public Map getProperties() { ); } + @Requires(property = "spec.name", value = "Http2PostTest") @Controller("/vertx/demo") public static class DemoController { @Get("/testGet") diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/ContextPathFilter.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/ContextPathFilter.java index f84efeef9d5..cb6da7238fd 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/ContextPathFilter.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/ContextPathFilter.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.publisher.Publishers; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; @@ -26,6 +27,7 @@ /** * Tests filters with the context path already prepended still work */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Filter("/context/path/**") public class ContextPathFilter implements HttpServerFilter { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/FirstFilter.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/FirstFilter.java index b4a65edd616..30081c7ed76 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/FirstFilter.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/FirstFilter.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.publisher.Publishers; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; @@ -28,6 +29,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Filter("/secure**") public class FirstFilter implements HttpFilter { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterContextPathSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterContextPathSpec.groovy index 65d39a18663..e4beec51838 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterContextPathSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterContextPathSpec.groovy @@ -11,7 +11,7 @@ class HttpFilterContextPathSpec extends AbstractMicronautSpec { @Override Map getConfiguration() { - super.getConfiguration() << ['micronaut.server.context-path': '/context/path'] + super.getConfiguration() << ['micronaut.server.context-path': '/context/path', 'tests': "io.micronaut.http.server.netty.interceptor"] } void "test interceptor execution and order - proceed"() { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterSpec.groovy index 20c03e3e4db..7fc9ac02fa5 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/HttpFilterSpec.groovy @@ -43,6 +43,7 @@ import spock.lang.Specification */ @MicronautTest @Property(name = 'spec.name', value = "HttpFilterSpec") +@Property(name = 'tests', value = "io.micronaut.http.server.netty.interceptor") class HttpFilterSpec extends Specification { @Inject diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecondFilter.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecondFilter.java index 76a12825f74..6a24202e888 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecondFilter.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecondFilter.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.convert.value.MutableConvertibleValues; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; @@ -28,6 +29,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Filter("/secure**") public class SecondFilter implements HttpFilter { @Override diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecureController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecureController.java index 4c9116dc0dc..399b340eb4b 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecureController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/SecureController.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.HttpResponse; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; @@ -23,6 +24,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Controller("/secure") public class SecureController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestReactiveFilter.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestReactiveFilter.java index 93ea6e6d885..f417e247dc3 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestReactiveFilter.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestReactiveFilter.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.annotation.Filter; @@ -27,6 +28,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Filter("/secure**") public class TestReactiveFilter implements HttpServerFilter{ diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestSecurityFilter.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestSecurityFilter.java index 46c40037392..200593d3c4b 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestSecurityFilter.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/interceptor/TestSecurityFilter.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.interceptor; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.publisher.Publishers; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; @@ -30,6 +31,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "tests", value = "io.micronaut.http.server.netty.interceptor") @Filter("/secure**") public class TestSecurityFilter implements HttpServerFilter { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ParameterController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ParameterController.java index 274f780d444..3fafc8c0356 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ParameterController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ParameterController.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.java; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.annotation.Nullable; import io.micronaut.http.HttpParameters; import io.micronaut.http.MediaType; @@ -31,6 +32,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "spec.name", value = "ParameterBindingSpec") @Controller("/java/parameter") public class ParameterController { @Get diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ResponseController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ResponseController.java index ad53bac3617..ace30d9c650 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ResponseController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/java/ResponseController.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.java; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.HttpMessage; import io.micronaut.http.HttpMethod; import io.micronaut.http.HttpResponse; @@ -29,6 +30,7 @@ * @author Graeme Rocher * @since 1.0 */ +@Requires(property = "spec.name", value = "ParameterBindingSpec") @Controller("/java/response") public class ResponseController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/LinuxNativeTransportSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/LinuxNativeTransportSpec.groovy index 4e756a3ae2a..e2aa6eea93c 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/LinuxNativeTransportSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/LinuxNativeTransportSpec.groovy @@ -25,6 +25,6 @@ class LinuxNativeTransportSpec extends AbstractMicronautSpec { @Override Map getConfiguration() { - super.getConfiguration() << ['micronaut.server.netty.use-native-transport': true] + super.getConfiguration() << ['micronaut.server.netty.use-native-transport': true, 'spec': 'TransportSpec'] } } diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/MacNativeTransportSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/MacNativeTransportSpec.groovy index 8884e6ac92a..ff5152236ad 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/MacNativeTransportSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/MacNativeTransportSpec.groovy @@ -27,6 +27,6 @@ class MacNativeTransportSpec extends AbstractMicronautSpec { @Override Map getConfiguration() { - super.getConfiguration() << ['micronaut.server.netty.use-native-transport': true] + super.getConfiguration() << ['micronaut.server.netty.use-native-transport': true, 'spec': 'TransportSpec'] } } diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/NativeTransportController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/NativeTransportController.java index 6aca3520d0a..a24759f0346 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/NativeTransportController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/nativetransport/NativeTransportController.java @@ -15,9 +15,11 @@ */ package io.micronaut.http.server.netty.nativetransport; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; +@Requires(property = "spec", value = "TransportSpec") @Controller("/native-transport") public class NativeTransportController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/redirect/RedirectSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/redirect/RedirectSpec.groovy index b8ab8efa0b5..442f211dc21 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/redirect/RedirectSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/redirect/RedirectSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.redirect import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpHeaders import io.micronaut.http.HttpResponse import io.micronaut.http.HttpStatus @@ -34,7 +35,7 @@ import spock.lang.Specification */ class RedirectSpec extends Specification { - @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'RedirectSpec']) @Shared @AutoCleanup HttpClient httpClient = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL(), new DefaultHttpClientConfiguration(followRedirects: false)) void 'test permanent redirect'() { @@ -57,6 +58,7 @@ class RedirectSpec extends Specification { !response.header(HttpHeaders.CONTENT_TYPE) } + @Requires(property = 'spec.name', value = 'RedirectSpec') @Controller("/redirect") static class RedirectController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/KeyValue.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/KeyValue.java new file mode 100644 index 00000000000..95636a5db7e --- /dev/null +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/KeyValue.java @@ -0,0 +1,26 @@ +package io.micronaut.http.server.netty.routing; + +import io.micronaut.core.annotation.Creator; +import io.micronaut.core.annotation.Introspected; + +@Introspected +public class KeyValue { + private String key; + private String value; + + @Creator + public static KeyValue of(String key, String value) { + final KeyValue keyValue = new KeyValue(); + keyValue.key = key; + keyValue.value = value; + return keyValue; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } +} diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyClient.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyClient.java new file mode 100644 index 00000000000..50054668f12 --- /dev/null +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyClient.java @@ -0,0 +1,23 @@ +package io.micronaut.http.server.netty.routing; + +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.client.annotation.Client; + +import java.util.List; + +@Client("/") +public interface MyClient { + @Post + KeyValue setRoot(@Body KeyValue body); + + @Get + KeyValue getRoot(); + + @Get("/{id}") + KeyValue getId(String id); + + @Get("/{id}/items") + List getRelations(String id); +} diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyController.java new file mode 100644 index 00000000000..e9f918ec34f --- /dev/null +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/MyController.java @@ -0,0 +1,37 @@ +package io.micronaut.http.server.netty.routing; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Post; +import io.micronaut.scheduling.TaskExecutors; +import io.micronaut.scheduling.annotation.ExecuteOn; + +import java.util.List; + +@Requires(property = "spec.name", value = "RootRoutingTest") +@Controller +@ExecuteOn(TaskExecutors.BLOCKING) +public class MyController { + + @Post + public KeyValue createRoot(@Body KeyValue body) { + return body; + } + + @Get + public KeyValue root() { + return KeyValue.of("hello", "world"); + } + + @Get("/{id}") + public KeyValue id(String id) { + return KeyValue.of("hello", id); + } + + @Get("/{id}/items") + public List items(String id) { + return List.of(KeyValue.of("hello", id), KeyValue.of("foo", "bar")); + } +} diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/RootRoutingTest.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/RootRoutingTest.java new file mode 100644 index 00000000000..79886d6e991 --- /dev/null +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/routing/RootRoutingTest.java @@ -0,0 +1,23 @@ +package io.micronaut.http.server.netty.routing; + +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +@Property(name = "spec.name", value = "RootRoutingTest") +@MicronautTest +class RootRoutingTest { + + @Inject + MyClient client; + + @Test + void testRootEndpoint() { + KeyValue kv = client.getRoot(); + Assertions.assertEquals("hello", kv.getKey()); + Assertions.assertEquals("world", kv.getValue()); + } + +} diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ssl/DeprecatedSslConfigurationSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ssl/DeprecatedSslConfigurationSpec.groovy index 5b1b22ce29a..8638a039bbe 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ssl/DeprecatedSslConfigurationSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/ssl/DeprecatedSslConfigurationSpec.groovy @@ -1,6 +1,7 @@ package io.micronaut.http.server.netty.ssl import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.http.HttpRequest import io.micronaut.http.annotation.Controller @@ -25,6 +26,7 @@ class DeprecatedSslConfigurationSpec extends Specification { def "self signed certificate is generated for #type configuration #property"() { given: EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [ + 'spec.name': 'DeprecatedSslConfigurationSpec', 'micronaut.server.ssl.port' : -1, 'micronaut.server.ssl.enabled' : true, 'micronaut.http.client.ssl.insecure-trust-all-certificates': true, @@ -57,6 +59,7 @@ class DeprecatedSslConfigurationSpec extends Specification { def "ssl port can be set with #type property #property"() { given: EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [ + 'spec.name': 'DeprecatedSslConfigurationSpec', (property) : -1, 'micronaut.server.ssl.enabled' : true, 'micronaut.http.client.ssl.insecure-trust-all-certificates': true, @@ -88,6 +91,7 @@ class DeprecatedSslConfigurationSpec extends Specification { "micronaut.server.ssl.port" | false | 'moved' } + @Requires(property = 'spec.name', value = 'DeprecatedSslConfigurationSpec') @Controller("/cert") static class TestController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/ErrorResponseSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/ErrorResponseSpec.groovy index c7d68a87eeb..40e3a18f8db 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/ErrorResponseSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/ErrorResponseSpec.groovy @@ -1,5 +1,7 @@ package io.micronaut.http.server.netty.stream +import io.micronaut.context.annotation.Property +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpStatus import io.micronaut.http.MediaType import io.micronaut.http.annotation.Controller @@ -16,6 +18,7 @@ import spock.lang.Issue import spock.lang.Specification @Issue('https://github.com/micronaut-projects/micronaut-core/issues/4862') +@Property(name = "spec.name", value = "ErrorResponseSpec") @MicronautTest class ErrorResponseSpec extends Specification { @Inject @@ -33,12 +36,14 @@ class ErrorResponseSpec extends Specification { } } + @Requires(property = 'spec.name', value = 'ErrorResponseSpec') @Client("/flowable") static interface FlowableClient { @Get(uri = "/error", consumes = MediaType.TEXT_PLAIN) Foo flowableError() } + @Requires(property = 'spec.name', value = 'ErrorResponseSpec') @Controller("/flowable") static class FlowableErrorController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxBodySpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxBodySpec.groovy index f25970dc0a7..843f77de3ea 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxBodySpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxBodySpec.groovy @@ -1,6 +1,7 @@ package io.micronaut.http.server.netty.stream import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse import io.micronaut.http.HttpStatus @@ -19,7 +20,7 @@ import spock.lang.Specification class FluxBodySpec extends Specification { - @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'FluxBodySpec']) @Shared @AutoCleanup HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURI()) void "test empty and non-empty flux"() { @@ -40,6 +41,7 @@ class FluxBodySpec extends Specification { e.response.status() == HttpStatus.BAD_REQUEST } + @Requires(property = 'spec.name', value = 'FluxBodySpec') @Controller("/body/flux/test") static class ReactiveController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxFullBodySpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxFullBodySpec.groovy index 0519b6a3a63..a6ef905d2aa 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxFullBodySpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/stream/FluxFullBodySpec.groovy @@ -1,12 +1,20 @@ package io.micronaut.http.server.netty.stream import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.http.HttpRequest +import io.micronaut.http.HttpResponse import io.micronaut.http.HttpStatus +import io.micronaut.http.annotation.Body +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Post import io.micronaut.http.client.HttpClient import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.http.server.netty.configuration.NettyHttpServerConfiguration import io.micronaut.runtime.server.EmbeddedServer +import org.reactivestreams.Publisher +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification @@ -15,7 +23,7 @@ class FluxFullBodySpec extends Specification { @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run( EmbeddedServer, - ["micronaut.server.netty.server-type": NettyHttpServerConfiguration.HttpServerType.FULL_CONTENT] + ["micronaut.server.netty.server-type": NettyHttpServerConfiguration.HttpServerType.FULL_CONTENT, 'spec.name': FluxFullBodySpec.simpleName] ) @Shared @AutoCleanup HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURI()) @@ -37,4 +45,15 @@ class FluxFullBodySpec extends Specification { e.response.status() == HttpStatus.BAD_REQUEST } + @Requires(property = 'spec.name', value = 'FluxFullBodySpec') + @Controller("/body/flux/test") + static class ReactiveController { + + @Post("/") + Mono> read(@Body Publisher body) { + return Flux.from(body).collectList() + .map(list -> HttpResponse.ok(list)) + } + } + } diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/threading/ThreadSelectionSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/threading/ThreadSelectionSpec.groovy index 0a371fd155f..2255238ba8c 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/threading/ThreadSelectionSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/threading/ThreadSelectionSpec.groovy @@ -1,6 +1,7 @@ package io.micronaut.http.server.netty.threading import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires import io.micronaut.core.annotation.Blocking import io.micronaut.core.annotation.NonBlocking import io.micronaut.http.HttpRequest @@ -45,7 +46,7 @@ class ThreadSelectionSpec extends Specification { void "test thread selection strategy #strategy"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['micronaut.server.thread-selection': strategy]) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec': getClass().getSimpleName(), 'micronaut.server.thread-selection': strategy]) ThreadSelectionClient client = embeddedServer.applicationContext.getBean(ThreadSelectionClient) expect: @@ -67,7 +68,7 @@ class ThreadSelectionSpec extends Specification { void "test thread selection strategy for reactive types #strategy"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['micronaut.server.thread-selection': strategy]) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec': getClass().getSimpleName(), 'micronaut.server.thread-selection': strategy]) ThreadSelectionClient client = embeddedServer.applicationContext.getBean(ThreadSelectionClient) @@ -90,7 +91,7 @@ class ThreadSelectionSpec extends Specification { void "test thread selection for exception handlers #strategy"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['micronaut.server.thread-selection': strategy]) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec': getClass().getSimpleName(), 'micronaut.server.thread-selection': strategy]) ThreadSelectionClient client = embeddedServer.applicationContext.getBean(ThreadSelectionClient) when: @@ -117,7 +118,7 @@ class ThreadSelectionSpec extends Specification { @Ignore // pending feature, only works sometimes: https://github.com/micronaut-projects/micronaut-core/pull/10104 void "test thread selection for error route #strategy"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['micronaut.server.thread-selection': strategy]) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec': getClass().getSimpleName(), 'micronaut.server.thread-selection': strategy]) ThreadSelectionClient client = embeddedServer.applicationContext.getBean(ThreadSelectionClient) when: @@ -140,7 +141,7 @@ class ThreadSelectionSpec extends Specification { void "test injecting an executor service does not inject the Netty event loop"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec': getClass().getSimpleName()]) ApplicationContext ctx = embeddedServer.applicationContext when: @@ -150,6 +151,7 @@ class ThreadSelectionSpec extends Specification { !ctx.getBeansOfType(ExecutorService).contains(eventLoopGroup) } + @Requires(property = "spec", value = "ThreadSelectionSpec") @Client("/thread-selection") static interface ThreadSelectionClient { @Get("/blocking") @@ -189,6 +191,7 @@ class ThreadSelectionSpec extends Specification { String scheduleException() } + @Requires(property = "spec", value = "ThreadSelectionSpec") @Controller("/thread-selection") static class ThreadSelectionController { @Get("/blocking") @@ -267,6 +270,7 @@ class ThreadSelectionSpec extends Specification { } } + @Requires(property = "spec", value = "ThreadSelectionSpec") @Filter("/thread-selection/alter**") static class ThreadSelectionFilter implements HttpServerFilter { @@ -304,6 +308,7 @@ class ThreadSelectionSpec extends Specification { } } + @Requires(property = "spec", value = "ThreadSelectionSpec") @Singleton static class MyExceptionHandler implements ExceptionHandler { @@ -313,6 +318,7 @@ class ThreadSelectionSpec extends Specification { } } + @Requires(property = "spec", value = "ThreadSelectionSpec") @Singleton static class MyScheduledExceptionHandler implements ExceptionHandler { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatClientWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatClientWebSocket.java index 4d2ecf914dc..78448507e9f 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatClientWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatClientWebSocket.java @@ -14,6 +14,7 @@ * limitations under the License. */ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; import io.micronaut.websocket.WebSocketPongMessage; import io.micronaut.websocket.WebSocketSession; @@ -32,6 +33,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Future; +@Requires(property = "spec.name", value = "BinaryWebSocketSpec") @ClientWebSocket("/binary/chat/{topic}/{username}") public abstract class BinaryChatClientWebSocket implements AutoCloseable{ diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatServerWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatServerWebSocket.java index 141e417db33..8c119875965 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatServerWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryChatServerWebSocket.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.context.ServerRequestContext; import io.micronaut.websocket.WebSocketSession; import io.micronaut.websocket.annotation.OnClose; @@ -24,6 +25,7 @@ import java.util.Set; +@Requires(property = "spec.name", value = "BinaryWebSocketSpec") @ServerWebSocket("/binary/chat/{topic}/{username}") public class BinaryChatServerWebSocket { @OnOpen diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryWebSocketSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryWebSocketSpec.groovy index d83c9c5be04..448b49bfad7 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryWebSocketSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/BinaryWebSocketSpec.groovy @@ -44,7 +44,7 @@ class BinaryWebSocketSpec extends Specification { void "test binary websocket exchange"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'BinaryWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) when: "a websocket connection is established" @@ -118,7 +118,7 @@ class BinaryWebSocketSpec extends Specification { void "test sending multiple frames for a single message"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'BinaryWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) when: "a websocket connection is established" @@ -152,7 +152,7 @@ class BinaryWebSocketSpec extends Specification { void "test sending many continuation frames"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'BinaryWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) when: "a websocket connection is established" @@ -186,7 +186,7 @@ class BinaryWebSocketSpec extends Specification { void "test sending ping messages"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'BinaryWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) when:"a websocket connection is established" @@ -210,7 +210,8 @@ class BinaryWebSocketSpec extends Specification { void "test per-message compression"() { given: def ctx = ApplicationContext.run([ - 'spec.name' : 'test per-message compression', + 'spec.name': 'BinaryWebSocketSpec', + 'method.name' : 'test per-message compression', 'micronaut.server.port': -1 ]) def cdcServer = ctx.getBean(CompressionDetectionCustomizerServer) @@ -267,7 +268,8 @@ class BinaryWebSocketSpec extends Specification { void "test per-message compression disabled"() { given: def ctx = ApplicationContext.run([ - 'spec.name' : 'test per-message compression', + 'spec.name': 'BinaryWebSocketSpec', + 'method.name' : 'test per-message compression', 'micronaut.server.port': -1, 'micronaut.http.client.ws.compression.enabled': false ]) @@ -322,7 +324,7 @@ class BinaryWebSocketSpec extends Specification { } @Singleton - @Requires(property = 'spec.name', value = 'test per-message compression') + @Requires(property = 'method.name', value = 'test per-message compression') static class CompressionDetectionCustomizerServer implements BeanCreatedEventListener { List pipelines = Collections.synchronizedList(new ArrayList<>()) @@ -352,7 +354,7 @@ class BinaryWebSocketSpec extends Specification { } @Singleton - @Requires(property = 'spec.name', value = 'test per-message compression') + @Requires(property = 'method.name', value = 'test per-message compression') static class CompressionDetectionCustomizerClient implements BeanCreatedEventListener { List pipelines = Collections.synchronizedList(new ArrayList<>()) diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatClientWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatClientWebSocket.java index a7479fa8147..e0cc78ab486 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatClientWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatClientWebSocket.java @@ -17,6 +17,7 @@ // tag::imports[] +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; import io.micronaut.http.HttpRequest; import io.micronaut.websocket.WebSocketSession; @@ -30,6 +31,7 @@ import java.util.concurrent.Future; // tag::class[] +@Requires(property = "spec.name", value = "SimpleTextWebSocketSpec") @ClientWebSocket("/chat/{topic}/{username}") // <1> public abstract class ChatClientWebSocket implements AutoCloseable { // <2> diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatServerWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatServerWebSocket.java index bde9b21a4b3..6f6ff72074d 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatServerWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ChatServerWebSocket.java @@ -16,6 +16,7 @@ package io.micronaut.http.server.netty.websocket; //tag::clazz[] +import io.micronaut.context.annotation.Requires; import io.micronaut.http.context.ServerRequestContext; import io.micronaut.websocket.WebSocketBroadcaster; import io.micronaut.websocket.WebSocketSession; @@ -26,6 +27,7 @@ import java.util.function.Predicate; +@Requires(property = "spec.name", value = "SimpleTextWebSocketSpec") @ServerWebSocket("/chat/{topic}/{username}") // <1> public class ChatServerWebSocket { private WebSocketBroadcaster broadcaster; diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ColludingController.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ColludingController.java index 232715415ff..9beb6282278 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ColludingController.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ColludingController.java @@ -15,12 +15,14 @@ */ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.PathVariable; import io.micronaut.http.annotation.Produces; +@Requires(property = "spec.name", value = "BinaryWebSocketSpec") @Controller("/binary/chat") public class ColludingController { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoChatClientWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoChatClientWebSocket.java index c1a46f7f8df..903e052e3fc 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoChatClientWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoChatClientWebSocket.java @@ -15,15 +15,18 @@ */ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.async.annotation.SingleResult; import io.micronaut.websocket.annotation.ClientWebSocket; import io.micronaut.websocket.annotation.OnMessage; import io.micronaut.websocket.annotation.OnOpen; import org.reactivestreams.Publisher; + import java.util.Collection; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Future; -import io.micronaut.core.async.annotation.SingleResult; +@Requires(property = "spec.name", value = "PojoWebSocketSpec") @ClientWebSocket("/pojo/chat/{topic}/{username}") public abstract class PojoChatClientWebSocket implements AutoCloseable { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoWebSocketSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoWebSocketSpec.groovy index 2831e9e1ba3..eb7052f2528 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoWebSocketSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/PojoWebSocketSpec.groovy @@ -27,7 +27,7 @@ class PojoWebSocketSpec extends Specification { void "test POJO websocket exchange"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'PojoWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) when: "a websocket connection is established" diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/QueryParamServerWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/QueryParamServerWebSocket.java index 329f3027a80..fdfb89adf57 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/QueryParamServerWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/QueryParamServerWebSocket.java @@ -1,5 +1,6 @@ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.annotation.QueryValue; import io.micronaut.websocket.WebSocketBroadcaster; import io.micronaut.websocket.WebSocketSession; @@ -8,6 +9,7 @@ import io.micronaut.websocket.annotation.OnOpen; import io.micronaut.websocket.annotation.ServerWebSocket; +@Requires(property = "spec.name", value = "SimpleTextWebSocketSpec") @ServerWebSocket("/charity") public class QueryParamServerWebSocket { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ReactivePojoChatServerWebSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ReactivePojoChatServerWebSocket.java index e7908058239..c157c53ac39 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ReactivePojoChatServerWebSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/ReactivePojoChatServerWebSocket.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.websocket; +import io.micronaut.context.annotation.Requires; import io.micronaut.http.context.ServerRequestContext; import io.micronaut.websocket.WebSocketBroadcaster; import io.micronaut.websocket.WebSocketSession; @@ -26,6 +27,7 @@ import java.util.function.Predicate; +@Requires(property = "spec.name", value = "PojoWebSocketSpec") @ServerWebSocket("/pojo/chat/{topic}/{username}") public class ReactivePojoChatServerWebSocket { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/SimpleTextWebSocketSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/SimpleTextWebSocketSpec.groovy index 82044027506..e1c33bcacd6 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/SimpleTextWebSocketSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/SimpleTextWebSocketSpec.groovy @@ -16,7 +16,6 @@ package io.micronaut.http.server.netty.websocket import io.micronaut.context.ApplicationContext -import io.micronaut.core.util.StreamUtils import io.micronaut.http.client.annotation.Client import io.micronaut.runtime.server.EmbeddedServer import io.micronaut.websocket.WebSocketClient @@ -34,7 +33,7 @@ class SimpleTextWebSocketSpec extends Specification { @Retry void "test simple text websocket exchange"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'SimpleTextWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 15 , delay: 0.5) def uri = embeddedServer.getURI() uri = new URI(scheme, uri.schemeSpecificPart, uri.fragment) // apply wss scheme @@ -113,6 +112,7 @@ class SimpleTextWebSocketSpec extends Specification { void "test simple text websocket connection over SSL"() { given: EmbeddedServer embeddedServer = ApplicationContext.builder([ + 'spec.name': 'SimpleTextWebSocketSpec', 'micronaut.server.netty.log-level':'TRACE', 'micronaut.server.ssl.enabled':true, 'micronaut.server.ssl.port': -1, @@ -198,7 +198,7 @@ class SimpleTextWebSocketSpec extends Specification { void "test simple text websocket connection with query"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder('micronaut.server.netty.log-level': 'TRACE').run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.builder('spec.name': 'SimpleTextWebSocketSpec', 'micronaut.server.netty.log-level': 'TRACE').run(EmbeddedServer) PollingConditions conditions = new PollingConditions(timeout: 2, delay: 0.5) when: "a websocket connection is established" @@ -224,6 +224,7 @@ class SimpleTextWebSocketSpec extends Specification { void "test a filter responding to a websocket upgrade request"() { given: EmbeddedServer embeddedServer = ApplicationContext.builder( + 'spec.name': 'SimpleTextWebSocketSpec', 'websocket-filter-respond': true ).run(EmbeddedServer) @@ -238,7 +239,7 @@ class SimpleTextWebSocketSpec extends Specification { void "test filters are invoked for web socket requests that don't match any routes"() { given: - EmbeddedServer embeddedServer = ApplicationContext.builder().run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'SimpleTextWebSocketSpec']) when: WebSocketClient wsClient = embeddedServer.applicationContext.createBean(WebSocketClient, embeddedServer.getURI()) diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/WebSocketErrorsSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/WebSocketErrorsSpec.groovy index 2987590896c..271bf7f4dde 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/WebSocketErrorsSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/WebSocketErrorsSpec.groovy @@ -31,7 +31,8 @@ class WebSocketErrorsSpec extends Specification { void "test idle timeout invokes onclose"() { given: EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [ - 'micronaut.server.idle-timeout': '5s' + 'micronaut.server.idle-timeout': '5s', + 'spec.name': 'WebSocketErrorsSpec' ]) WebSocketClient wsClient = embeddedServer.applicationContext.createBean(WebSocketClient, embeddedServer.getURI()) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) @@ -62,7 +63,7 @@ class WebSocketErrorsSpec extends Specification { void "test error from on message handler without @OnMessage closes the connection"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'WebSocketErrorsSpec']) WebSocketClient wsClient = embeddedServer.applicationContext.createBean(WebSocketClient, embeddedServer.getURI()) PollingConditions conditions = new PollingConditions(timeout: 15, delay: 0.5) @@ -92,7 +93,7 @@ class WebSocketErrorsSpec extends Specification { void "test error from on message handler without @OnMessage invokes @OnError handler"() { given: - EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'WebSocketErrorsSpec']) WebSocketClient wsClient = embeddedServer.applicationContext.createBean(WebSocketClient, embeddedServer.getURI()) PollingConditions conditions = new PollingConditions(timeout: 15 , delay: 0.5) diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/ErrorsClient.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/ErrorsClient.java index 3bed71cac33..4ef147cbe1f 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/ErrorsClient.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/ErrorsClient.java @@ -15,6 +15,7 @@ */ package io.micronaut.http.server.netty.websocket.errors; +import io.micronaut.context.annotation.Requires; import io.micronaut.websocket.CloseReason; import io.micronaut.websocket.WebSocketSession; import io.micronaut.websocket.annotation.ClientWebSocket; @@ -23,6 +24,7 @@ import io.micronaut.websocket.annotation.OnMessage; import io.micronaut.websocket.annotation.OnOpen; +@Requires(property = "spec.name", value = "WebSocketErrorsSpec") @ClientWebSocket public abstract class ErrorsClient implements AutoCloseable { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocket.java index f1f1ad174ec..9a02e399154 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocket.java @@ -15,10 +15,12 @@ */ package io.micronaut.http.server.netty.websocket.errors; +import io.micronaut.context.annotation.Requires; import io.micronaut.websocket.annotation.OnClose; import io.micronaut.websocket.annotation.OnMessage; import io.micronaut.websocket.annotation.ServerWebSocket; +@Requires(property = "spec.name", value = "WebSocketErrorsSpec") @ServerWebSocket("/ws/errors/message") public class MessageErrorSocket { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocketWithOnError.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocketWithOnError.java index 2a49b191fab..7bbace3efaa 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocketWithOnError.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/MessageErrorSocketWithOnError.java @@ -15,12 +15,14 @@ */ package io.micronaut.http.server.netty.websocket.errors; +import io.micronaut.context.annotation.Requires; import io.micronaut.websocket.CloseReason; import io.micronaut.websocket.WebSocketSession; import io.micronaut.websocket.annotation.OnError; import io.micronaut.websocket.annotation.OnMessage; import io.micronaut.websocket.annotation.ServerWebSocket; +@Requires(property = "spec.name", value = "WebSocketErrorsSpec") @ServerWebSocket("/ws/errors/message-onerror") public class MessageErrorSocketWithOnError { diff --git a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/TimeoutErrorSocket.java b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/TimeoutErrorSocket.java index a53a2ac9112..19ed661e459 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/TimeoutErrorSocket.java +++ b/http-server-netty/src/test/groovy/io/micronaut/http/server/netty/websocket/errors/TimeoutErrorSocket.java @@ -15,16 +15,17 @@ */ package io.micronaut.http.server.netty.websocket.errors; +import io.micronaut.context.annotation.Requires; import io.micronaut.websocket.annotation.OnClose; import io.micronaut.websocket.annotation.OnMessage; import io.micronaut.websocket.annotation.ServerWebSocket; +@Requires(property = "spec.name", value = "WebSocketErrorsSpec") @ServerWebSocket("/ws/timeout/message") public class TimeoutErrorSocket { boolean closed = false; - @OnMessage public void onMessage(String blah) { System.out.println("blah = " + blah); diff --git a/http-server-netty/src/test/groovy/io/micronaut/runtime/ExecutorServiceWithMultipleEventLoopsSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/runtime/ExecutorServiceWithMultipleEventLoopsSpec.groovy index 12d4c4de24e..6ad9280aa8c 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/runtime/ExecutorServiceWithMultipleEventLoopsSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/runtime/ExecutorServiceWithMultipleEventLoopsSpec.groovy @@ -17,6 +17,7 @@ package io.micronaut.runtime import io.micronaut.context.ApplicationContext import io.micronaut.context.annotation.Context +import io.micronaut.context.annotation.Requires import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get import io.micronaut.scheduling.TaskExecutors @@ -35,6 +36,7 @@ class ExecutorServiceWithMultipleEventLoopsSpec extends Specification { 'micronaut.netty.event-loops.clients.num-threads': 1, 'micronaut.netty.event-loops.abc.num-threads': 1, 'micronaut.netty.event-loops.xyz.num-threads': 1, + 'spec.name': 'ExecutorServiceWithMultipleEventLoopsSpec' ]) then: @@ -45,6 +47,7 @@ class ExecutorServiceWithMultipleEventLoopsSpec extends Specification { applicationContext.close() } + @Requires(property = 'spec.name', value = 'ExecutorServiceWithMultipleEventLoopsSpec') @Controller static class MyController1 { @@ -62,6 +65,7 @@ class ExecutorServiceWithMultipleEventLoopsSpec extends Specification { } + @Requires(property = 'spec.name', value = 'ExecutorServiceWithMultipleEventLoopsSpec') @Context @Controller static class MyController2 { diff --git a/http-server-netty/src/test/groovy/io/micronaut/runtime/http/scope/RequestScopeSpec.groovy b/http-server-netty/src/test/groovy/io/micronaut/runtime/http/scope/RequestScopeSpec.groovy index 3ff9c0f5917..d7784aa7be6 100644 --- a/http-server-netty/src/test/groovy/io/micronaut/runtime/http/scope/RequestScopeSpec.groovy +++ b/http-server-netty/src/test/groovy/io/micronaut/runtime/http/scope/RequestScopeSpec.groovy @@ -16,6 +16,7 @@ package io.micronaut.runtime.http.scope import io.micronaut.context.annotation.Prototype +import io.micronaut.context.annotation.Requires import io.micronaut.context.event.ApplicationEventListener import io.micronaut.http.HttpRequest import io.micronaut.http.annotation.Controller @@ -149,6 +150,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { result == "OK" } + @Requires(property = "spec.name", value = "RequestScopeSpec") @RequestScope static class RequestBean { @@ -174,6 +176,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } } + @Requires(property = "spec.name", value = "RequestScopeSpec") @RequestScope static class SimpleRequestBean { @@ -193,6 +196,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } + @Requires(property = "spec.name", value = "RequestScopeSpec") @Prototype static class SimpleBean { @@ -205,6 +209,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } + @Requires(property = "spec.name", value = "RequestScopeSpec") @Controller static class SimpleTestController { final SimpleRequestBean simpleRequestBean @@ -231,6 +236,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } } + @Requires(property = "spec.name", value = "RequestScopeSpec") @RequestScope static class RequestAwareBean implements RequestAware { @@ -242,6 +248,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } } + @Requires(property = "spec.name", value = "RequestScopeSpec") @Singleton static class MessageService { @@ -266,6 +273,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } } + @Requires(property = "spec.name", value = "RequestScopeSpec") @Controller static class TestController { @@ -294,6 +302,7 @@ class RequestScopeSpec extends AbstractMicronautSpec { } } + @Requires(property = "spec.name", value = "RequestScopeSpec") @Singleton static class ReqTerminatedListener implements ApplicationEventListener { int callCount diff --git a/http-server-tck/src/main/java/io/micronaut/http/server/tck/tests/routing/RootRoutingTest.java b/http-server-tck/src/main/java/io/micronaut/http/server/tck/tests/routing/RootRoutingTest.java new file mode 100644 index 00000000000..b065bea1d4c --- /dev/null +++ b/http-server-tck/src/main/java/io/micronaut/http/server/tck/tests/routing/RootRoutingTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.http.server.tck.tests.routing; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.Introspected; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpStatus; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.tck.AssertionUtils; +import io.micronaut.http.tck.BodyAssertion; +import io.micronaut.http.tck.HttpResponseAssertion; +import io.micronaut.http.tck.TestScenario; +import io.micronaut.scheduling.TaskExecutors; +import io.micronaut.scheduling.annotation.ExecuteOn; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; + +@SuppressWarnings({ + "java:S5960", // We're allowed assertions, as these are used in tests only + "checkstyle:MissingJavadocType", + "checkstyle:DesignForExtension" +}) +public class RootRoutingTest { + public static final String SPEC_NAME = "RootRoutingTest"; + + @Test + void testRouting() throws IOException { + TestScenario.asserts(SPEC_NAME, + HttpRequest.GET("/"), + (server, request) -> AssertionUtils.assertDoesNotThrow(server, request, HttpResponseAssertion.builder() + .status(HttpStatus.OK) + .body(BodyAssertion.builder().body(""" + {"key":"hello","value":"world"}""").equals()) + .build())); + } + + @Requires(property = "spec.name", value = SPEC_NAME) + @Controller + @ExecuteOn(TaskExecutors.BLOCKING) + static class MyController { + + @Post + public KeyValue createRoot(@Body KeyValue body) { + return body; + } + + @Get + public KeyValue root() { + return new KeyValue("hello", "world"); + } + + @Get("/{id}") + public KeyValue id(String id) { + return new KeyValue("hello", id); + } + + @Get("/{id}/items") + public List items(String id) { + return List.of(new KeyValue("hello", id), new KeyValue("foo", "bar")); + } + } + + @Introspected + private record KeyValue(String key, String value) { + } + +} diff --git a/http/src/main/java/io/micronaut/http/uri/UriTemplateMatcher.java b/http/src/main/java/io/micronaut/http/uri/UriTemplateMatcher.java index 103d0064560..cb44ed2ffa6 100644 --- a/http/src/main/java/io/micronaut/http/uri/UriTemplateMatcher.java +++ b/http/src/main/java/io/micronaut/http/uri/UriTemplateMatcher.java @@ -68,7 +68,7 @@ private UriTemplateMatcher(String templateString, List p this.parts = parts; List variables = new ArrayList<>(); this.segments = provideMatchSegments(parts, variables); - this.isRoot = segments.length == 0 || segments[0].type == SegmentType.LITERAL && isRoot(segments[0].value); + this.isRoot = segments.length == 0 || segments.length == 1 && segments[0].type == SegmentType.LITERAL && isRoot(segments[0].value); this.variables = Collections.unmodifiableList(variables); } @@ -269,9 +269,10 @@ public UriMatchInfo tryMatch(@NonNull String uri) { int parameterIndex = uri.indexOf('?'); if (parameterIndex > -1) { uri = uri.substring(0, parameterIndex); - } - if (uri.endsWith("/")) { - uri = uri.substring(0, uri.length() - 1); + length = uri.length(); + if (length > 1 && uri.charAt(length - 1) == '/') { + uri = uri.substring(0, length - 1); + } } if (variables.isEmpty()) { if (uri.equals(templateString)) {