Skip to content

Commit 997d1b3

Browse files
violetaggrstoyanchev
authored andcommitted
Enable leak detection in Netty 5 tests
See gh-29310
1 parent 57bbc09 commit 997d1b3

File tree

7 files changed

+45
-11
lines changed

7 files changed

+45
-11
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ configure([rootProject] + javaProjects) { project ->
8484
systemProperty("java.awt.headless", "true")
8585
systemProperty("testGroups", project.properties.get("testGroups"))
8686
systemProperty("io.netty.leakDetection.level", "paranoid")
87+
systemProperty("io.netty5.leakDetectionLevel", "paranoid")
88+
systemProperty("io.netty5.leakDetection.targetRecords", "32")
89+
systemProperty("io.netty5.buffer.lifecycleTracingEnabled", "true")
90+
systemProperty("io.netty5.buffer.leakDetectionEnabled", "true")
8791
jvmArgs(["--add-opens=java.base/java.lang=ALL-UNNAMED",
8892
"--add-opens=java.base/java.util=ALL-UNNAMED"])
8993
}

spring-core/src/test/java/org/springframework/core/codec/Netty5BufferDecoderTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ public void decodeToMono() {
8787
}
8888

8989
private Consumer<Buffer> expectByteBuffer(Buffer expected) {
90-
return actual -> assertThat(actual).isEqualTo(expected);
90+
return actual -> {
91+
try (actual; expected) {
92+
assertThat(actual).isEqualTo(expected);
93+
}
94+
};
9195
}
9296

9397
}

spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferTests.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,12 @@ void asByteBufferIndexLength(DataBufferFactory bufferFactory) {
534534
ByteBuffer result = buffer.asByteBuffer(1, 2);
535535
assertThat(result.capacity()).isEqualTo(2);
536536

537-
assumeFalse(bufferFactory instanceof Netty5DataBufferFactory,
538-
"Netty 5 does share the internal buffer");
537+
boolean isNetty5DataBufferFactory = bufferFactory instanceof Netty5DataBufferFactory;
538+
if (isNetty5DataBufferFactory) {
539+
DataBufferUtils.release(buffer);
540+
}
541+
542+
assumeFalse(isNetty5DataBufferFactory, "Netty 5 does share the internal buffer");
539543

540544
buffer.write((byte) 'c');
541545
assertThat(result.remaining()).isEqualTo(2);
@@ -774,6 +778,9 @@ void spr16351(DataBufferFactory bufferFactory) {
774778

775779
assertThat(result).isEqualTo(bytes);
776780

781+
if (bufferFactory instanceof Netty5DataBufferFactory) {
782+
release(slice);
783+
}
777784
release(buffer);
778785
}
779786

spring-core/src/testFixtures/java/org/springframework/core/testfixture/codec/AbstractDecoderTests.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Map;
2121
import java.util.function.Consumer;
2222

23+
import io.netty5.buffer.Buffer;
2324
import org.junit.jupiter.api.Test;
2425
import org.reactivestreams.Publisher;
2526
import reactor.core.publisher.Flux;
@@ -209,7 +210,13 @@ protected void testDecodeError(Publisher<DataBuffer> input, ResolvableType outpu
209210

210211
Flux<DataBuffer> buffer = Mono.from(input).concatWith(Flux.error(new InputException()));
211212
assertThatExceptionOfType(InputException.class).isThrownBy(() ->
212-
this.decoder.decode(buffer, outputType, mimeType, hints).blockLast(Duration.ofSeconds(5)));
213+
this.decoder.decode(buffer, outputType, mimeType, hints)
214+
.doOnNext(o -> {
215+
if (o instanceof Buffer buf) {
216+
buf.close();
217+
}
218+
})
219+
.blockLast(Duration.ofSeconds(5)));
213220
}
214221

215222
/**
@@ -226,7 +233,12 @@ protected void testDecodeError(Publisher<DataBuffer> input, ResolvableType outpu
226233
protected void testDecodeCancel(Publisher<DataBuffer> input, ResolvableType outputType,
227234
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
228235

229-
Flux<?> result = this.decoder.decode(input, outputType, mimeType, hints);
236+
Flux<?> result = this.decoder.decode(input, outputType, mimeType, hints)
237+
.doOnNext(o -> {
238+
if (o instanceof Buffer buf) {
239+
buf.close();
240+
}
241+
});
230242
StepVerifier.create(result).expectNextCount(1).thenCancel().verify();
231243
}
232244

spring-webflux/src/main/java/org/springframework/web/reactive/socket/WebSocketMessage.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.core.io.buffer.DataBuffer;
2323
import org.springframework.core.io.buffer.DataBufferUtils;
24+
import org.springframework.core.io.buffer.Netty5DataBufferFactory;
2425
import org.springframework.lang.Nullable;
2526
import org.springframework.util.Assert;
2627
import org.springframework.util.ObjectUtils;
@@ -128,8 +129,15 @@ public String getPayloadAsText(Charset charset) {
128129
* @see DataBufferUtils#retain(DataBuffer)
129130
*/
130131
public WebSocketMessage retain() {
131-
DataBufferUtils.retain(this.payload);
132-
return this;
132+
if (!(this.nativeMessage instanceof io.netty5.handler.codec.http.websocketx.WebSocketFrame frame) ) {
133+
DataBufferUtils.retain(this.payload);
134+
return this;
135+
}
136+
else {
137+
io.netty5.handler.codec.http.websocketx.WebSocketFrame newFrame = frame.send().receive();
138+
DataBuffer newPayload = ((Netty5DataBufferFactory) this.payload.factory()).wrap(newFrame.binaryData());
139+
return new WebSocketMessage(this.type, newPayload, newFrame);
140+
}
133141
}
134142

135143
/**

spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/Netty5WebSocketSessionSupport.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ public Netty5DataBufferFactory bufferFactory() {
7575

7676

7777
protected WebSocketMessage toMessage(WebSocketFrame frame) {
78-
WebSocketFrame newFrame = frame.send().receive();
79-
DataBuffer payload = bufferFactory().wrap(newFrame.binaryData());
80-
return new WebSocketMessage(messageTypes.get(newFrame.getClass()), payload, newFrame);
78+
DataBuffer payload = bufferFactory().wrap(frame.binaryData());
79+
return new WebSocketMessage(messageTypes.get(frame.getClass()), payload, frame);
8180
}
8281

8382
protected WebSocketFrame toFrame(WebSocketMessage message) {

spring-webflux/src/test/java/org/springframework/web/reactive/socket/WebSocketIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public Mono<Void> handle(WebSocketSession session) {
220220
return Mono.deferContextual(contextView -> {
221221
String key = ServerWebExchangeContextFilter.EXCHANGE_CONTEXT_ATTRIBUTE;
222222
assertThat(contextView.getOrEmpty(key).orElse(null)).isNotNull();
223-
return session.send(session.receive().doOnNext(WebSocketMessage::retain));
223+
return session.send(session.receive().map(WebSocketMessage::retain));
224224
});
225225
}
226226
}

0 commit comments

Comments
 (0)