1717package org .springframework .test .web .reactive .server ;
1818
1919import java .net .URI ;
20+ import java .nio .charset .StandardCharsets ;
2021import java .time .Duration ;
2122
23+ import io .netty .buffer .PooledByteBufAllocator ;
24+ import org .junit .jupiter .api .AfterEach ;
2225import org .junit .jupiter .api .Test ;
26+ import reactor .core .publisher .Flux ;
2327import reactor .core .publisher .Mono ;
2428
29+ import org .springframework .core .io .buffer .DataBuffer ;
30+ import org .springframework .core .io .buffer .NettyDataBufferFactory ;
31+ import org .springframework .core .testfixture .io .buffer .LeakAwareDataBufferFactory ;
2532import org .springframework .http .HttpMethod ;
2633import org .springframework .http .HttpStatus ;
2734import org .springframework .http .client .reactive .ClientHttpConnector ;
3037import org .springframework .mock .http .client .reactive .MockClientHttpRequest ;
3138import org .springframework .mock .http .client .reactive .MockClientHttpResponse ;
3239import org .springframework .web .reactive .function .client .ClientRequest ;
40+ import org .springframework .web .reactive .function .client .ClientResponse ;
3341import org .springframework .web .reactive .function .client .ExchangeFunction ;
3442import org .springframework .web .reactive .function .client .ExchangeFunctions ;
3543
4452 */
4553public class WiretapConnectorTests {
4654
55+ private final LeakAwareDataBufferFactory bufferFactory =
56+ new LeakAwareDataBufferFactory (new NettyDataBufferFactory (PooledByteBufAllocator .DEFAULT ));
57+
58+ @ AfterEach
59+ void tearDown () {
60+ this .bufferFactory .checkForLeaks ();
61+ }
62+
4763 @ Test
4864 public void captureAndClaim () {
4965 ClientHttpRequest request = new MockClientHttpRequest (HttpMethod .GET , "/test" );
5066 ClientHttpResponse response = new MockClientHttpResponse (HttpStatus .OK );
51- ClientHttpConnector connector = ( method , uri , fn ) -> fn . apply ( request ). then ( Mono . just ( response ) );
67+ ClientHttpConnector connector = createConnector ( request , response );
5268
5369 ClientRequest clientRequest = ClientRequest .create (HttpMethod .GET , URI .create ("/test" ))
5470 .header (WebTestClient .WEBTESTCLIENT_REQUEST_ID , "1" ).build ();
@@ -62,4 +78,47 @@ public void captureAndClaim() {
6278 assertThat (result .getUrl ().toString ()).isEqualTo ("/test" );
6379 }
6480
81+ @ Test
82+ void shouldReleaseBuffers () {
83+ MockClientHttpRequest request = new MockClientHttpRequest (HttpMethod .GET , "/test" );
84+ MockClientHttpResponse response = new MockClientHttpResponse (HttpStatus .OK );
85+ response .setBody (Flux .just (toDataBuffer ("Hello Spring" )));
86+ ClientHttpConnector connector = createConnector (request , response );
87+
88+ ClientRequest clientRequest = ClientRequest .create (HttpMethod .GET , URI .create ("/test" ))
89+ .header (WebTestClient .WEBTESTCLIENT_REQUEST_ID , "1" ).build ();
90+
91+ WiretapConnector wiretapConnector = new WiretapConnector (connector , null );
92+ ExchangeFunction function = ExchangeFunctions .create (wiretapConnector );
93+ function .exchange (clientRequest ).block (ofMillis (0 ));
94+ ExchangeResult result = wiretapConnector .getExchangeResult ("1" , null , Duration .ZERO );
95+ result .getResponseBodyContent ();
96+ }
97+
98+ @ Test
99+ void shouldReleaseBuffersOnlyOnce () {
100+ MockClientHttpRequest request = new MockClientHttpRequest (HttpMethod .GET , "/test" );
101+ MockClientHttpResponse response = new MockClientHttpResponse (HttpStatus .OK );
102+ response .setBody (Flux .just (toDataBuffer ("Hello Spring" ), toDataBuffer ("Hello Spring" ), toDataBuffer ("Hello Spring" ), toDataBuffer ("Hello Spring" )));
103+ ClientHttpConnector connector = createConnector (request , response );
104+
105+ ClientRequest clientRequest = ClientRequest .create (HttpMethod .GET , URI .create ("/test" ))
106+ .header (WebTestClient .WEBTESTCLIENT_REQUEST_ID , "1" ).build ();
107+
108+ WiretapConnector wiretapConnector = new WiretapConnector (connector , null );
109+ ExchangeFunction function = ExchangeFunctions .create (wiretapConnector );
110+ function .exchange (clientRequest ).flatMap (ClientResponse ::releaseBody ).block (ofMillis (0 ));
111+ ExchangeResult result = wiretapConnector .getExchangeResult ("1" , null , Duration .ZERO );
112+ result .getResponseBodyContent ();
113+ }
114+
115+ private ClientHttpConnector createConnector (ClientHttpRequest request , ClientHttpResponse response ) {
116+ return (method , uri , fn ) -> fn .apply (request ).then (Mono .just (response ));
117+ }
118+
119+ private DataBuffer toDataBuffer (String s ) {
120+ DataBuffer buffer = this .bufferFactory .allocateBuffer (256 );
121+ buffer .write (s .getBytes (StandardCharsets .UTF_8 ));
122+ return buffer ;
123+ }
65124}
0 commit comments