Add ByteBuf leak detection @Rule
This commit introduces a JUnit rule that detects ByteBuf leaks in subclasses of AbstractDataBufferAllocatingTestCase.
This commit is contained in:
parent
b33d8c6ade
commit
621df7c978
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -49,6 +49,12 @@ public class NettyDataBufferFactory implements DataBufferFactory {
|
|||
this.byteBufAllocator = byteBufAllocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@code ByteBufAllocator} used by this factory.
|
||||
*/
|
||||
public ByteBufAllocator getByteBufAllocator() {
|
||||
return this.byteBufAllocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NettyDataBuffer allocateBuffer() {
|
||||
|
|
|
@ -28,9 +28,7 @@ import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
|
|||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
|
@ -59,5 +57,7 @@ public class DataBufferDecoderTests extends AbstractDataBufferAllocatingTestCase
|
|||
null, Collections.emptyMap());
|
||||
|
||||
assertSame(source, output);
|
||||
|
||||
release(fooBuffer, barBuffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
|
|||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
|
@ -63,6 +61,8 @@ public class DataBufferEncoderTests extends AbstractDataBufferAllocatingTestCase
|
|||
null, Collections.emptyMap());
|
||||
|
||||
assertSame(source, output);
|
||||
|
||||
release(fooBuffer, barBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,16 +18,22 @@ package org.springframework.core.io.buffer;
|
|||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.PoolArenaMetric;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.buffer.PooledByteBufAllocatorMetric;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.Verifier;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
|
@ -43,14 +49,18 @@ public abstract class AbstractDataBufferAllocatingTestCase {
|
|||
return new Object[][] {
|
||||
{new NettyDataBufferFactory(new UnpooledByteBufAllocator(true))},
|
||||
{new NettyDataBufferFactory(new UnpooledByteBufAllocator(false))},
|
||||
{new NettyDataBufferFactory(new PooledByteBufAllocator(true))},
|
||||
{new NettyDataBufferFactory(new PooledByteBufAllocator(false))},
|
||||
// disable caching for reliable leak detection, see https://github.com/netty/netty/issues/5275
|
||||
{new NettyDataBufferFactory(new PooledByteBufAllocator(true, 1, 1, 8192, 11, 0, 0, 0, true))},
|
||||
{new NettyDataBufferFactory(new PooledByteBufAllocator(false, 1, 1, 8192, 11, 0, 0, 0, true))},
|
||||
{new DefaultDataBufferFactory(true)},
|
||||
{new DefaultDataBufferFactory(false)}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Rule
|
||||
public final Verifier leakDetector = new LeakDetector();
|
||||
|
||||
protected DataBuffer createDataBuffer(int capacity) {
|
||||
return this.bufferFactory.allocateBuffer(capacity);
|
||||
}
|
||||
|
@ -75,4 +85,30 @@ public abstract class AbstractDataBufferAllocatingTestCase {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
private class LeakDetector extends Verifier {
|
||||
|
||||
@Override
|
||||
protected void verify() throws Throwable {
|
||||
if (bufferFactory instanceof NettyDataBufferFactory) {
|
||||
ByteBufAllocator byteBufAllocator =
|
||||
((NettyDataBufferFactory) bufferFactory).getByteBufAllocator();
|
||||
if (byteBufAllocator instanceof PooledByteBufAllocator) {
|
||||
PooledByteBufAllocator pooledByteBufAllocator =
|
||||
(PooledByteBufAllocator) byteBufAllocator;
|
||||
PooledByteBufAllocatorMetric metric = pooledByteBufAllocator.metric();
|
||||
long allocations = calculateAllocations(metric.directArenas()) +
|
||||
calculateAllocations(metric.heapArenas());
|
||||
assertTrue("ByteBuf leak detected: " + allocations +
|
||||
" allocations were not released", allocations == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long calculateAllocations(List<PoolArenaMetric> metrics) {
|
||||
return metrics.stream().mapToLong(PoolArenaMetric::numActiveAllocations).sum();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -280,6 +280,8 @@ public class DataBufferTests extends AbstractDataBufferAllocatingTestCase {
|
|||
bytes = new byte[9];
|
||||
buffer.read(bytes);
|
||||
assertArrayEquals(" World!!!".getBytes(StandardCharsets.UTF_8), bytes);
|
||||
|
||||
release(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue