Fix Memory release not correctly in Multipart Decoder (#11188)
Motivation: 2 years ago a change remove the default clearing of all HttpData, whatever they are disk based or memory based. A lot of users were probably releasing HttpData directly, so there was no issue. But now, it seems, and as the Javadoc said, that `decoder.destroy()` shall clean up also Memory based HttpData, and not only Disk based HttpData as currently. Change: - Add in `destroy()` method the necessary code to release if necessary the underlying Memory based HttpDatas. - Change one Junit Test (using Mixed, Memory and Disk based factories) in order to check the correctness of this behavior and to really act as a handler (releasing buffers or requests). - Modify one Junit core to check validity when a delimiter is present in the Chunk but not CRLF/LF (false delimiter), to ensure correctness. Result: No more issue on memory leak Note that still the List and the Map are not cleaned, since they were not before. No change is done on this, since it could produce backward issue compatibility. Fix issues #11175 and #11184
This commit is contained in:
parent
c0708fc464
commit
e7330490e3
@ -43,7 +43,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
|
|
||||||
import static io.netty.util.internal.ObjectUtil.*;
|
import static io.netty.util.internal.ObjectUtil.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,13 +335,8 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
|
|||||||
|
|
||||||
ByteBuf buf = content.content();
|
ByteBuf buf = content.content();
|
||||||
if (undecodedChunk == null) {
|
if (undecodedChunk == null) {
|
||||||
undecodedChunk = isLastChunk ?
|
undecodedChunk =
|
||||||
// Take a slice instead of copying when the first chunk is also the last
|
// Since the Handler will release the incoming later on, we need to copy it
|
||||||
// as undecodedChunk.writeBytes will never be called.
|
|
||||||
buf.retainedSlice() :
|
|
||||||
// Maybe we should better not copy here for performance reasons but this will need
|
|
||||||
// more care by the caller to release the content in a correct manner later
|
|
||||||
// So maybe something to optimize on a later stage
|
|
||||||
//
|
//
|
||||||
// We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
|
// We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
|
||||||
// which is not really usable for us as we may exceed it once we add more bytes.
|
// which is not really usable for us as we may exceed it once we add more bytes.
|
||||||
@ -958,8 +952,15 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
// Release all data items, including those not yet pulled
|
// Release all data items, including those not yet pulled, only file based items
|
||||||
cleanFiles();
|
cleanFiles();
|
||||||
|
// Clean Memory based data
|
||||||
|
for (InterfaceHttpData httpData : bodyListHttpData) {
|
||||||
|
// Might have been already released by the user
|
||||||
|
if (httpData.refCnt() > 0) {
|
||||||
|
httpData.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
|
|||||||
this.factory = checkNotNull(factory, "factory");
|
this.factory = checkNotNull(factory, "factory");
|
||||||
try {
|
try {
|
||||||
if (request instanceof HttpContent) {
|
if (request instanceof HttpContent) {
|
||||||
// Offer automatically if the given request is als type of HttpContent
|
// Offer automatically if the given request is as type of HttpContent
|
||||||
// See #1089
|
// See #1089
|
||||||
offer((HttpContent) request);
|
offer((HttpContent) request);
|
||||||
} else {
|
} else {
|
||||||
@ -287,13 +287,8 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
|
|||||||
|
|
||||||
ByteBuf buf = content.content();
|
ByteBuf buf = content.content();
|
||||||
if (undecodedChunk == null) {
|
if (undecodedChunk == null) {
|
||||||
undecodedChunk = isLastChunk ?
|
undecodedChunk =
|
||||||
// Take a slice instead of copying when the first chunk is also the last
|
// Since the Handler will release the incoming later on, we need to copy it
|
||||||
// as undecodedChunk.writeBytes will never be called.
|
|
||||||
buf.retainedSlice() :
|
|
||||||
// Maybe we should better not copy here for performance reasons but this will need
|
|
||||||
// more care by the caller to release the content in a correct manner later
|
|
||||||
// So maybe something to optimize on a later stage.
|
|
||||||
//
|
//
|
||||||
// We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
|
// We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
|
||||||
// which is not really usable for us as we may exceed it once we add more bytes.
|
// which is not really usable for us as we may exceed it once we add more bytes.
|
||||||
@ -693,8 +688,15 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
// Release all data items, including those not yet pulled
|
// Release all data items, including those not yet pulled, only file based items
|
||||||
cleanFiles();
|
cleanFiles();
|
||||||
|
// Clean Memory based data
|
||||||
|
for (InterfaceHttpData httpData : bodyListHttpData) {
|
||||||
|
// Might have been already released by the user
|
||||||
|
if (httpData.refCnt() > 0) {
|
||||||
|
httpData.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
|
|
||||||
|
@ -88,7 +88,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
// Create decoder instance to test.
|
// Create decoder instance to test.
|
||||||
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
||||||
|
|
||||||
decoder.offer(new DefaultHttpContent(Unpooled.copiedBuffer(body, CharsetUtil.UTF_8)));
|
ByteBuf buf = Unpooled.copiedBuffer(body, CharsetUtil.UTF_8);
|
||||||
|
decoder.offer(new DefaultHttpContent(buf));
|
||||||
decoder.offer(new DefaultHttpContent(Unpooled.EMPTY_BUFFER));
|
decoder.offer(new DefaultHttpContent(Unpooled.EMPTY_BUFFER));
|
||||||
|
|
||||||
// Validate it's enough chunks to decode upload.
|
// Validate it's enough chunks to decode upload.
|
||||||
@ -102,6 +103,7 @@ public class HttpPostRequestDecoderTest {
|
|||||||
data, upload.getString(CharsetUtil.UTF_8));
|
data, upload.getString(CharsetUtil.UTF_8));
|
||||||
upload.release();
|
upload.release();
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
buf.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,8 +136,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
// Create decoder instance to test.
|
// Create decoder instance to test.
|
||||||
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
||||||
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://github.com/netty/netty/issues/2544
|
// See https://github.com/netty/netty/issues/2544
|
||||||
@ -181,8 +183,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertNotNull(datar);
|
assertNotNull(datar);
|
||||||
assertEquals(datas[i].getBytes(CharsetUtil.UTF_8).length, datar.length);
|
assertEquals(datas[i].getBytes(CharsetUtil.UTF_8).length, datar.length);
|
||||||
|
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,8 +217,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
// Create decoder instance to test.
|
// Create decoder instance to test.
|
||||||
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
||||||
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://github.com/netty/netty/issues/1848
|
// See https://github.com/netty/netty/issues/1848
|
||||||
@ -276,6 +278,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
|
|
||||||
aDecodedData.release();
|
aDecodedData.release();
|
||||||
aDecoder.destroy();
|
aDecoder.destroy();
|
||||||
|
aSmallBuf.release();
|
||||||
|
aLargeBuf.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://github.com/netty/netty/issues/2305
|
// See https://github.com/netty/netty/issues/2305
|
||||||
@ -373,8 +377,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
// Create decoder instance to test.
|
// Create decoder instance to test.
|
||||||
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
||||||
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -403,8 +407,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertTrue(part1 instanceof FileUpload);
|
assertTrue(part1 instanceof FileUpload);
|
||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
assertEquals("tmp 0.txt", fileUpload.getFilename());
|
assertEquals("tmp 0.txt", fileUpload.getFilename());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -434,8 +438,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
// Create decoder instance to test without any exception.
|
// Create decoder instance to test without any exception.
|
||||||
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
|
||||||
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
assertFalse(decoder.getBodyHttpDatas().isEmpty());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -467,8 +471,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
byte[] fileBytes = fileUpload.get();
|
byte[] fileBytes = fileUpload.get();
|
||||||
assertTrue("the filecontent should not be decoded", filecontent.equals(new String(fileBytes)));
|
assertTrue("the filecontent should not be decoded", filecontent.equals(new String(fileBytes)));
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -497,7 +501,7 @@ public class HttpPostRequestDecoderTest {
|
|||||||
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
||||||
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
||||||
} finally {
|
} finally {
|
||||||
req.release();
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +534,7 @@ public class HttpPostRequestDecoderTest {
|
|||||||
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
||||||
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
||||||
} finally {
|
} finally {
|
||||||
req.release();
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,8 +585,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
|
assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
|
||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/netty/netty/pull/7265
|
// https://github.com/netty/netty/pull/7265
|
||||||
@ -617,8 +621,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
|
assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
|
||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/netty/netty/pull/7265
|
// https://github.com/netty/netty/pull/7265
|
||||||
@ -649,7 +653,7 @@ public class HttpPostRequestDecoderTest {
|
|||||||
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
||||||
assertTrue(e.getCause() instanceof ArrayIndexOutOfBoundsException);
|
assertTrue(e.getCause() instanceof ArrayIndexOutOfBoundsException);
|
||||||
} finally {
|
} finally {
|
||||||
req.release();
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +685,7 @@ public class HttpPostRequestDecoderTest {
|
|||||||
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
|
||||||
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
|
||||||
} finally {
|
} finally {
|
||||||
req.release();
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,8 +716,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertTrue(part1 instanceof FileUpload);
|
assertTrue(part1 instanceof FileUpload);
|
||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
assertEquals("tmp-0.txt", fileUpload.getFilename());
|
assertEquals("tmp-0.txt", fileUpload.getFilename());
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/netty/netty/issues/8575
|
// https://github.com/netty/netty/issues/8575
|
||||||
@ -832,8 +836,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
FileUpload fileUpload = (FileUpload) part1;
|
FileUpload fileUpload = (FileUpload) part1;
|
||||||
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
|
||||||
|
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -869,8 +873,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
assertTrue(attr.getByteBuf().isDirect());
|
assertTrue(attr.getByteBuf().isDirect());
|
||||||
assertEquals("los angeles", attr.getValue());
|
assertEquals("los angeles", attr.getValue());
|
||||||
|
|
||||||
req.release();
|
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
assertTrue(req.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -987,7 +991,8 @@ public class HttpPostRequestDecoderTest {
|
|||||||
int bytesLastChunk = 10000;
|
int bytesLastChunk = 10000;
|
||||||
int fileSize = bytesPerChunk * nbChunks + bytesLastChunk; // set Xmx to a number lower than this and it crashes
|
int fileSize = bytesPerChunk * nbChunks + bytesLastChunk; // set Xmx to a number lower than this and it crashes
|
||||||
|
|
||||||
String prefix = "--861fbeab-cd20-470c-9609-d40a0f704466\n" +
|
String delimiter = "--861fbeab-cd20-470c-9609-d40a0f704466";
|
||||||
|
String prefix = delimiter + "\n" +
|
||||||
"Content-Disposition: form-data; name=\"image\"; filename=\"guangzhou.jpeg\"\n" +
|
"Content-Disposition: form-data; name=\"image\"; filename=\"guangzhou.jpeg\"\n" +
|
||||||
"Content-Type: image/jpeg\n" +
|
"Content-Type: image/jpeg\n" +
|
||||||
"Content-Length: " + fileSize + "\n" +
|
"Content-Length: " + fileSize + "\n" +
|
||||||
@ -1003,8 +1008,10 @@ public class HttpPostRequestDecoderTest {
|
|||||||
request.headers().set("content-length", prefix.length() + fileSize + suffix.length());
|
request.headers().set("content-length", prefix.length() + fileSize + suffix.length());
|
||||||
|
|
||||||
HttpPostMultipartRequestDecoder decoder = new HttpPostMultipartRequestDecoder(factory, request);
|
HttpPostMultipartRequestDecoder decoder = new HttpPostMultipartRequestDecoder(factory, request);
|
||||||
decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(prefix.getBytes(CharsetUtil.UTF_8))));
|
ByteBuf buf = Unpooled.wrappedBuffer(prefix.getBytes(CharsetUtil.UTF_8));
|
||||||
|
decoder.offer(new DefaultHttpContent(buf));
|
||||||
assertNotNull(((HttpData) decoder.currentPartialHttpData()).content());
|
assertNotNull(((HttpData) decoder.currentPartialHttpData()).content());
|
||||||
|
buf.release();
|
||||||
|
|
||||||
byte[] body = new byte[bytesPerChunk];
|
byte[] body = new byte[bytesPerChunk];
|
||||||
Arrays.fill(body, (byte) 1);
|
Arrays.fill(body, (byte) 1);
|
||||||
@ -1020,11 +1027,16 @@ public class HttpPostRequestDecoderTest {
|
|||||||
|
|
||||||
byte[] bsuffix1 = suffix1.getBytes(CharsetUtil.UTF_8);
|
byte[] bsuffix1 = suffix1.getBytes(CharsetUtil.UTF_8);
|
||||||
byte[] previousLastbody = new byte[bytesLastChunk - bsuffix1.length];
|
byte[] previousLastbody = new byte[bytesLastChunk - bsuffix1.length];
|
||||||
|
byte[] bdelimiter = delimiter.getBytes(CharsetUtil.UTF_8);
|
||||||
byte[] lastbody = new byte[2 * bsuffix1.length];
|
byte[] lastbody = new byte[2 * bsuffix1.length];
|
||||||
Arrays.fill(previousLastbody, (byte) 1);
|
Arrays.fill(previousLastbody, (byte) 1);
|
||||||
previousLastbody[0] = HttpConstants.CR;
|
previousLastbody[0] = HttpConstants.CR;
|
||||||
previousLastbody[1] = HttpConstants.LF;
|
previousLastbody[1] = HttpConstants.LF;
|
||||||
Arrays.fill(lastbody, (byte) 1);
|
Arrays.fill(lastbody, (byte) 1);
|
||||||
|
// put somewhere a not valid delimiter
|
||||||
|
for (int i = 0; i < bdelimiter.length; i++) {
|
||||||
|
previousLastbody[i + 10] = bdelimiter[i];
|
||||||
|
}
|
||||||
lastbody[0] = HttpConstants.CR;
|
lastbody[0] = HttpConstants.CR;
|
||||||
lastbody[1] = HttpConstants.LF;
|
lastbody[1] = HttpConstants.LF;
|
||||||
for (int i = 0; i < bsuffix1.length; i++) {
|
for (int i = 0; i < bsuffix1.length; i++) {
|
||||||
@ -1055,12 +1067,18 @@ public class HttpPostRequestDecoderTest {
|
|||||||
}
|
}
|
||||||
assertTrue("Capacity should be less than 1M", decoder.getCurrentAllocatedCapacity()
|
assertTrue("Capacity should be less than 1M", decoder.getCurrentAllocatedCapacity()
|
||||||
< 1024 * 1024);
|
< 1024 * 1024);
|
||||||
for (InterfaceHttpData httpData: decoder.getBodyHttpDatas()) {
|
InterfaceHttpData[] httpDatas = decoder.getBodyHttpDatas().toArray(new InterfaceHttpData[0]);
|
||||||
httpData.release();
|
for (InterfaceHttpData httpData : httpDatas) {
|
||||||
factory.removeHttpDataFromClean(request, httpData);
|
assertEquals("Before cleanAllHttpData should be 1", 1, httpData.refCnt());
|
||||||
}
|
}
|
||||||
factory.cleanAllHttpData();
|
factory.cleanAllHttpData();
|
||||||
|
for (InterfaceHttpData httpData : httpDatas) {
|
||||||
|
assertEquals("Before cleanAllHttpData should be 1 if in Memory", inMemory? 1 : 0, httpData.refCnt());
|
||||||
|
}
|
||||||
decoder.destroy();
|
decoder.destroy();
|
||||||
|
for (InterfaceHttpData httpData : httpDatas) {
|
||||||
|
assertEquals("RefCnt should be 0", 0, httpData.refCnt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1121,7 +1139,9 @@ public class HttpPostRequestDecoderTest {
|
|||||||
for (int i = 0; i < bp2.length; i++) {
|
for (int i = 0; i < bp2.length; i++) {
|
||||||
prefix[bp1.length + 2 + i] = bp2[i];
|
prefix[bp1.length + 2 + i] = bp2[i];
|
||||||
}
|
}
|
||||||
decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(prefix)));
|
ByteBuf buf = Unpooled.wrappedBuffer(prefix);
|
||||||
|
decoder.offer(new DefaultHttpContent(buf));
|
||||||
|
buf.release();
|
||||||
byte[] body = new byte[bytesPerItem];
|
byte[] body = new byte[bytesPerItem];
|
||||||
Arrays.fill(body, (byte) rank);
|
Arrays.fill(body, (byte) rank);
|
||||||
ByteBuf content = Unpooled.wrappedBuffer(body, 0, bytesPerItem);
|
ByteBuf content = Unpooled.wrappedBuffer(body, 0, bytesPerItem);
|
||||||
|
Loading…
Reference in New Issue
Block a user