|
19 | 19 | import java.nio.ByteBuffer;
|
20 | 20 | import java.nio.charset.StandardCharsets;
|
21 | 21 | import java.util.ArrayList;
|
| 22 | +import java.util.Collections; |
22 | 23 | import java.util.List;
|
| 24 | +import java.util.Map; |
23 | 25 | import java.util.function.Consumer;
|
24 | 26 | import java.util.function.Supplier;
|
25 | 27 |
|
26 | 28 | import org.junit.jupiter.api.Test;
|
27 | 29 | import org.reactivestreams.Publisher;
|
28 | 30 | import reactor.core.publisher.Flux;
|
29 | 31 | import reactor.core.publisher.Mono;
|
| 32 | +import reactor.netty.channel.AbortedException; |
30 | 33 | import reactor.test.StepVerifier;
|
31 | 34 |
|
| 35 | +import org.springframework.core.ResolvableType; |
32 | 36 | import org.springframework.core.io.buffer.DataBuffer;
|
33 | 37 | import org.springframework.core.io.buffer.DefaultDataBuffer;
|
34 | 38 | import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
| 39 | +import org.springframework.core.testfixture.io.buffer.LeakAwareDataBufferFactory; |
35 | 40 | import org.springframework.http.HttpHeaders;
|
36 | 41 | import org.springframework.http.HttpStatus;
|
37 | 42 | import org.springframework.http.MediaType;
|
38 | 43 | import org.springframework.http.ResponseCookie;
|
| 44 | +import org.springframework.http.codec.EncoderHttpMessageWriter; |
| 45 | +import org.springframework.http.codec.HttpMessageWriter; |
| 46 | +import org.springframework.http.codec.json.Jackson2JsonEncoder; |
| 47 | +import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest; |
| 48 | +import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse; |
39 | 49 |
|
40 | 50 | import static org.assertj.core.api.Assertions.assertThat;
|
41 | 51 |
|
@@ -186,6 +196,25 @@ void beforeCommitErrorShouldLeaveResponseNotCommitted() {
|
186 | 196 | });
|
187 | 197 | }
|
188 | 198 |
|
| 199 | + @Test // gh-26232 |
| 200 | + void monoResponseShouldNotLeakIfCancelled() { |
| 201 | + LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory(); |
| 202 | + MockServerHttpRequest request = MockServerHttpRequest.get("/").build(); |
| 203 | + MockServerHttpResponse response = new MockServerHttpResponse(bufferFactory); |
| 204 | + response.setWriteHandler(flux -> { |
| 205 | + throw AbortedException.beforeSend(); |
| 206 | + }); |
| 207 | + |
| 208 | + HttpMessageWriter<Object> messageWriter = new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()); |
| 209 | + Mono<Void> result = messageWriter.write(Mono.just(Collections.singletonMap("foo", "bar")), |
| 210 | + ResolvableType.forClass(Mono.class), ResolvableType.forClass(Map.class), null, |
| 211 | + request, response, Collections.emptyMap()); |
| 212 | + |
| 213 | + StepVerifier.create(result).expectError(AbortedException.class).verify(); |
| 214 | + |
| 215 | + bufferFactory.checkForLeaks(); |
| 216 | + } |
| 217 | + |
189 | 218 |
|
190 | 219 | private DefaultDataBuffer wrap(String a) {
|
191 | 220 | return DefaultDataBufferFactory.sharedInstance.wrap(ByteBuffer.wrap(a.getBytes(StandardCharsets.UTF_8)));
|
|
0 commit comments