migrate java8: use lambda and method reference (#8781)

Motivation:

We can use lambdas now as we use Java8.

Modification:

use lambda function for all package, #8751 only migrate transport package.

Result:

Code cleanup.
This commit is contained in:
田欧 2019-01-29 21:06:05 +08:00 committed by Norman Maurer
parent 185efa5b7c
commit 6222101924
192 changed files with 2727 additions and 4999 deletions

View File

@ -28,109 +28,59 @@ public interface ByteBufProcessor extends ByteProcessor {
* @deprecated Use {@link ByteProcessor#FIND_NUL}. * @deprecated Use {@link ByteProcessor#FIND_NUL}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NUL = new ByteBufProcessor() { ByteBufProcessor FIND_NUL = value -> value != 0;
@Override
public boolean process(byte value) throws Exception {
return value != 0;
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_NON_NUL}. * @deprecated Use {@link ByteProcessor#FIND_NON_NUL}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NON_NUL = new ByteBufProcessor() { ByteBufProcessor FIND_NON_NUL = value -> value == 0;
@Override
public boolean process(byte value) throws Exception {
return value == 0;
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_CR}. * @deprecated Use {@link ByteProcessor#FIND_CR}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_CR = new ByteBufProcessor() { ByteBufProcessor FIND_CR = value -> value != '\r';
@Override
public boolean process(byte value) throws Exception {
return value != '\r';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_NON_CR}. * @deprecated Use {@link ByteProcessor#FIND_NON_CR}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NON_CR = new ByteBufProcessor() { ByteBufProcessor FIND_NON_CR = value -> value == '\r';
@Override
public boolean process(byte value) throws Exception {
return value == '\r';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_LF}. * @deprecated Use {@link ByteProcessor#FIND_LF}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_LF = new ByteBufProcessor() { ByteBufProcessor FIND_LF = value -> value != '\n';
@Override
public boolean process(byte value) throws Exception {
return value != '\n';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_NON_LF}. * @deprecated Use {@link ByteProcessor#FIND_NON_LF}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NON_LF = new ByteBufProcessor() { ByteBufProcessor FIND_NON_LF = value -> value == '\n';
@Override
public boolean process(byte value) throws Exception {
return value == '\n';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_CRLF}. * @deprecated Use {@link ByteProcessor#FIND_CRLF}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_CRLF = new ByteBufProcessor() { ByteBufProcessor FIND_CRLF = value -> value != '\r' && value != '\n';
@Override
public boolean process(byte value) throws Exception {
return value != '\r' && value != '\n';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_NON_CRLF}. * @deprecated Use {@link ByteProcessor#FIND_NON_CRLF}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NON_CRLF = new ByteBufProcessor() { ByteBufProcessor FIND_NON_CRLF = value -> value == '\r' || value == '\n';
@Override
public boolean process(byte value) throws Exception {
return value == '\r' || value == '\n';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_LINEAR_WHITESPACE}. * @deprecated Use {@link ByteProcessor#FIND_LINEAR_WHITESPACE}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_LINEAR_WHITESPACE = new ByteBufProcessor() { ByteBufProcessor FIND_LINEAR_WHITESPACE = value -> value != ' ' && value != '\t';
@Override
public boolean process(byte value) throws Exception {
return value != ' ' && value != '\t';
}
};
/** /**
* @deprecated Use {@link ByteProcessor#FIND_NON_LINEAR_WHITESPACE}. * @deprecated Use {@link ByteProcessor#FIND_NON_LINEAR_WHITESPACE}.
*/ */
@Deprecated @Deprecated
ByteBufProcessor FIND_NON_LINEAR_WHITESPACE = new ByteBufProcessor() { ByteBufProcessor FIND_NON_LINEAR_WHITESPACE = value -> value == ' ' || value == '\t';
@Override
public boolean process(byte value) throws Exception {
return value == ' ' || value == '\t';
}
};
} }

View File

@ -1254,12 +1254,7 @@ public final class ByteBufUtil {
/** /**
* Aborts on a byte which is not a valid ASCII character. * Aborts on a byte which is not a valid ASCII character.
*/ */
private static final ByteProcessor FIND_NON_ASCII = new ByteProcessor() { private static final ByteProcessor FIND_NON_ASCII = value -> value >= 0;
@Override
public boolean process(byte value) {
return value >= 0;
}
};
/** /**
* Returns {@code true} if the specified {@link ByteBuf} starting at {@code index} with {@code length} is valid * Returns {@code true} if the specified {@link ByteBuf} starting at {@code index} with {@code length} is valid

View File

@ -2089,16 +2089,13 @@ public abstract class AbstractByteBufTest {
final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final AtomicReference<Throwable> errorRef = new AtomicReference<>();
List<Thread> threads = new ArrayList<>(); List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(() -> {
@Override try {
public void run() { while (errorRef.get() == null && counter.decrementAndGet() > 0) {
try { assertEquals("Hello, World!", buffer.toString(CharsetUtil.ISO_8859_1));
while (errorRef.get() == null && counter.decrementAndGet() > 0) {
assertEquals("Hello, World!", buffer.toString(CharsetUtil.ISO_8859_1));
}
} catch (Throwable cause) {
errorRef.compareAndSet(null, cause);
} }
} catch (Throwable cause) {
errorRef.compareAndSet(null, cause);
} }
}); });
threads.add(thread); threads.add(thread);
@ -2358,34 +2355,31 @@ public abstract class AbstractByteBufTest {
final CountDownLatch latch = new CountDownLatch(60000); final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11); final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
new Thread(new Runnable() { new Thread(() -> {
@Override while (latch.getCount() > 0) {
public void run() { ByteBuf buf;
while (latch.getCount() > 0) { if (slice) {
ByteBuf buf; buf = buffer.slice();
if (slice) { } else {
buf = buffer.slice(); buf = buffer.duplicate();
} else { }
buf = buffer.duplicate(); TestGatheringByteChannel channel = new TestGatheringByteChannel();
}
TestGatheringByteChannel channel = new TestGatheringByteChannel();
while (buf.isReadable()) { while (buf.isReadable()) {
try { try {
buf.readBytes(channel, buf.readableBytes()); buf.readBytes(channel, buf.readableBytes());
} catch (IOException e) { } catch (IOException e) {
// Never happens // Never happens
return; return;
}
} }
assertArrayEquals(bytes, channel.writtenBytes());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
assertArrayEquals(bytes, channel.writtenBytes());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
}).start(); }).start();
} }
@ -2413,34 +2407,31 @@ public abstract class AbstractByteBufTest {
final CountDownLatch latch = new CountDownLatch(60000); final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11); final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
new Thread(new Runnable() { new Thread(() -> {
@Override while (latch.getCount() > 0) {
public void run() { ByteBuf buf;
while (latch.getCount() > 0) { if (slice) {
ByteBuf buf; buf = buffer.slice();
if (slice) { } else {
buf = buffer.slice(); buf = buffer.duplicate();
} else { }
buf = buffer.duplicate(); ByteArrayOutputStream out = new ByteArrayOutputStream();
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
while (buf.isReadable()) { while (buf.isReadable()) {
try { try {
buf.readBytes(out, buf.readableBytes()); buf.readBytes(out, buf.readableBytes());
} catch (IOException e) { } catch (IOException e) {
// Never happens // Never happens
return; return;
}
} }
assertArrayEquals(bytes, out.toByteArray());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
assertArrayEquals(bytes, out.toByteArray());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
}).start(); }).start();
} }
@ -2469,33 +2460,30 @@ public abstract class AbstractByteBufTest {
final CountDownLatch latch = new CountDownLatch(60000); final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11); final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
new Thread(new Runnable() { new Thread(() -> {
@Override while (cause.get() == null && latch.getCount() > 0) {
public void run() { ByteBuf buf;
while (cause.get() == null && latch.getCount() > 0) { if (slice) {
ByteBuf buf; buf = buffer.slice();
if (slice) { } else {
buf = buffer.slice(); buf = buffer.duplicate();
} else {
buf = buffer.duplicate();
}
byte[] array = new byte[8];
buf.readBytes(array);
assertArrayEquals(bytes, array);
Arrays.fill(array, (byte) 0);
buf.getBytes(0, array);
assertArrayEquals(bytes, array);
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
byte[] array = new byte[8];
buf.readBytes(array);
assertArrayEquals(bytes, array);
Arrays.fill(array, (byte) 0);
buf.getBytes(0, array);
assertArrayEquals(bytes, array);
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
} }
}).start(); }).start();
} }
@ -4643,30 +4631,24 @@ public abstract class AbstractByteBufTest {
final ByteBuf buffer = newBuffer(4); final ByteBuf buffer = newBuffer(4);
assertEquals(1, buffer.refCnt()); assertEquals(1, buffer.refCnt());
final AtomicInteger cnt = new AtomicInteger(Integer.MAX_VALUE); final AtomicInteger cnt = new AtomicInteger(Integer.MAX_VALUE);
Thread t1 = new Thread(new Runnable() { Thread t1 = new Thread(() -> {
@Override boolean released;
public void run() { if (parameter) {
boolean released; released = buffer.release(buffer.refCnt());
if (parameter) { } else {
released = buffer.release(buffer.refCnt()); released = buffer.release();
} else { }
released = buffer.release(); assertTrue(released);
} Thread t2 = new Thread(() -> {
assertTrue(released); cnt.set(buffer.refCnt());
Thread t2 = new Thread(new Runnable() { latch.countDown();
@Override });
public void run() { t2.start();
cnt.set(buffer.refCnt()); try {
latch.countDown(); // Keep Thread alive a bit so the ThreadLocal caches are not freed
} innerLatch.await();
}); } catch (InterruptedException ignore) {
t2.start(); // ignore
try {
// Keep Thread alive a bit so the ThreadLocal caches are not freed
innerLatch.await();
} catch (InterruptedException ignore) {
// ignore
}
} }
}); });
t1.start(); t1.start();

View File

@ -680,16 +680,13 @@ public class ByteBufUtilTest {
final AtomicReference<Throwable> errorRef = new AtomicReference<>(); final AtomicReference<Throwable> errorRef = new AtomicReference<>();
List<Thread> threads = new ArrayList<>(); List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(() -> {
@Override try {
public void run() { while (errorRef.get() == null && counter.decrementAndGet() > 0) {
try { assertTrue(ByteBufUtil.isText(buffer, CharsetUtil.ISO_8859_1));
while (errorRef.get() == null && counter.decrementAndGet() > 0) {
assertTrue(ByteBufUtil.isText(buffer, CharsetUtil.ISO_8859_1));
}
} catch (Throwable cause) {
errorRef.compareAndSet(null, cause);
} }
} catch (Throwable cause) {
errorRef.compareAndSet(null, cause);
} }
}); });
threads.add(thread); threads.add(thread);

View File

@ -257,23 +257,20 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest<Poo
final AtomicBoolean threadCachesCreated = new AtomicBoolean(true); final AtomicBoolean threadCachesCreated = new AtomicBoolean(true);
final Runnable task = new Runnable() { final Runnable task = () -> {
@Override ByteBuf buf = allocator.newHeapBuffer(1024, 1024);
public void run() { for (int i = 0; i < buf.capacity(); i++) {
ByteBuf buf = allocator.newHeapBuffer(1024, 1024); buf.writeByte(0);
for (int i = 0; i < buf.capacity(); i++) {
buf.writeByte(0);
}
// Make sure that thread caches are actually created,
// so that down below we are not testing for zero
// thread caches without any of them ever having been initialized.
if (allocator.metric().numThreadLocalCaches() == 0) {
threadCachesCreated.set(false);
}
buf.release();
} }
// Make sure that thread caches are actually created,
// so that down below we are not testing for zero
// thread caches without any of them ever having been initialized.
if (allocator.metric().numThreadLocalCaches() == 0) {
threadCachesCreated.set(false);
}
buf.release();
}; };
for (int i = 0; i < numArenas; i++) { for (int i = 0; i < numArenas; i++) {
@ -368,39 +365,32 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest<Poo
throws InterruptedException { throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch cacheLatch = new CountDownLatch(1); final CountDownLatch cacheLatch = new CountDownLatch(1);
final Thread t = new FastThreadLocalThread(new Runnable() { final Thread t = new FastThreadLocalThread(() -> {
ByteBuf buf = allocator.newHeapBuffer(1024, 1024);
@Override // Countdown the latch after we allocated a buffer. At this point the cache must exists.
public void run() { cacheLatch.countDown();
ByteBuf buf = allocator.newHeapBuffer(1024, 1024);
// Countdown the latch after we allocated a buffer. At this point the cache must exists. buf.writeZero(buf.capacity());
cacheLatch.countDown();
buf.writeZero(buf.capacity()); try {
latch.await();
try { } catch (InterruptedException e) {
latch.await(); throw new IllegalStateException(e);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
buf.release();
FastThreadLocal.removeAll();
} }
buf.release();
FastThreadLocal.removeAll();
}); });
t.start(); t.start();
// Wait until we allocated a buffer and so be sure the thread was started and the cache exists. // Wait until we allocated a buffer and so be sure the thread was started and the cache exists.
cacheLatch.await(); cacheLatch.await();
return new ThreadCache() { return () -> {
@Override latch.countDown();
public void destroy() throws InterruptedException { t.join();
latch.countDown();
t.join();
}
}; };
} }

View File

@ -57,24 +57,14 @@ public class CombinedHttpHeaders extends DefaultHttpHeaders {
private CsvValueEscaper<Object> objectEscaper() { private CsvValueEscaper<Object> objectEscaper() {
if (objectEscaper == null) { if (objectEscaper == null) {
objectEscaper = new CsvValueEscaper<Object>() { objectEscaper = value -> StringUtil.escapeCsv(valueConverter().convertObject(value), true);
@Override
public CharSequence escape(Object value) {
return StringUtil.escapeCsv(valueConverter().convertObject(value), true);
}
};
} }
return objectEscaper; return objectEscaper;
} }
private CsvValueEscaper<CharSequence> charSequenceEscaper() { private CsvValueEscaper<CharSequence> charSequenceEscaper() {
if (charSequenceEscaper == null) { if (charSequenceEscaper == null) {
charSequenceEscaper = new CsvValueEscaper<CharSequence>() { charSequenceEscaper = value -> StringUtil.escapeCsv(value, true);
@Override
public CharSequence escape(CharSequence value) {
return StringUtil.escapeCsv(value, true);
}
};
} }
return charSequenceEscaper; return charSequenceEscaper;
} }

View File

@ -44,30 +44,24 @@ import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
*/ */
public class DefaultHttpHeaders extends HttpHeaders { public class DefaultHttpHeaders extends HttpHeaders {
private static final int HIGHEST_INVALID_VALUE_CHAR_MASK = ~15; private static final int HIGHEST_INVALID_VALUE_CHAR_MASK = ~15;
private static final ByteProcessor HEADER_NAME_VALIDATOR = new ByteProcessor() { private static final ByteProcessor HEADER_NAME_VALIDATOR = value -> {
@Override validateHeaderNameElement(value);
public boolean process(byte value) throws Exception { return true;
validateHeaderNameElement(value);
return true;
}
}; };
static final NameValidator<CharSequence> HttpNameValidator = new NameValidator<CharSequence>() { static final NameValidator<CharSequence> HttpNameValidator = name -> {
@Override if (name == null || name.length() == 0) {
public void validateName(CharSequence name) { throw new IllegalArgumentException("empty headers are not allowed [" + name + "]");
if (name == null || name.length() == 0) { }
throw new IllegalArgumentException("empty headers are not allowed [" + name + "]"); if (name instanceof AsciiString) {
try {
((AsciiString) name).forEachByte(HEADER_NAME_VALIDATOR);
} catch (Exception e) {
PlatformDependent.throwException(e);
} }
if (name instanceof AsciiString) { } else {
try { // Go through each character in the name
((AsciiString) name).forEachByte(HEADER_NAME_VALIDATOR); for (int index = 0; index < name.length(); ++index) {
} catch (Exception e) { validateHeaderNameElement(name.charAt(index));
PlatformDependent.throwException(e);
}
} else {
// Go through each character in the name
for (int index = 0; index < name.length(); ++index) {
validateHeaderNameElement(name.charAt(index));
}
} }
} }
}; };

View File

@ -115,15 +115,12 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
} }
private static final class TrailingHttpHeaders extends DefaultHttpHeaders { private static final class TrailingHttpHeaders extends DefaultHttpHeaders {
private static final NameValidator<CharSequence> TrailerNameValidator = new NameValidator<CharSequence>() { private static final NameValidator<CharSequence> TrailerNameValidator = name -> {
@Override DefaultHttpHeaders.HttpNameValidator.validateName(name);
public void validateName(CharSequence name) { if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(name)
DefaultHttpHeaders.HttpNameValidator.validateName(name); || HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(name)
if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(name) || HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(name)) {
|| HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(name) throw new IllegalArgumentException("prohibited trailing header: " + name);
|| HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(name)) {
throw new IllegalArgumentException("prohibited trailing header: " + name);
}
} }
}; };

View File

@ -251,23 +251,17 @@ public class HttpObjectAggregator
if (oversized instanceof FullHttpMessage || if (oversized instanceof FullHttpMessage ||
!HttpUtil.is100ContinueExpected(oversized) && !HttpUtil.isKeepAlive(oversized)) { !HttpUtil.is100ContinueExpected(oversized) && !HttpUtil.isKeepAlive(oversized)) {
ChannelFuture future = ctx.writeAndFlush(TOO_LARGE_CLOSE.retainedDuplicate()); ChannelFuture future = ctx.writeAndFlush(TOO_LARGE_CLOSE.retainedDuplicate());
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> {
@Override if (!future1.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { logger.debug("Failed to send a 413 Request Entity Too Large.", future1.cause());
if (!future.isSuccess()) {
logger.debug("Failed to send a 413 Request Entity Too Large.", future.cause());
}
ctx.close();
} }
ctx.close();
}); });
} else { } else {
ctx.writeAndFlush(TOO_LARGE.retainedDuplicate()).addListener(new ChannelFutureListener() { ctx.writeAndFlush(TOO_LARGE.retainedDuplicate()).addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { logger.debug("Failed to send a 413 Request Entity Too Large.", future.cause());
if (!future.isSuccess()) { ctx.close();
logger.debug("Failed to send a 413 Request Entity Too Large.", future.cause());
ctx.close();
}
} }
}); });
} }

View File

@ -91,26 +91,23 @@ public final class ClientCookieEncoder extends CookieEncoder {
* Sort cookies into decreasing order of path length, breaking ties by sorting into increasing chronological * Sort cookies into decreasing order of path length, breaking ties by sorting into increasing chronological
* order of creation time, as recommended by RFC 6265. * order of creation time, as recommended by RFC 6265.
*/ */
private static final Comparator<Cookie> COOKIE_COMPARATOR = new Comparator<Cookie>() { private static final Comparator<Cookie> COOKIE_COMPARATOR = (c1, c2) -> {
@Override String path1 = c1.path();
public int compare(Cookie c1, Cookie c2) { String path2 = c2.path();
String path1 = c1.path(); // Cookies with unspecified path default to the path of the request. We don't
String path2 = c2.path(); // know the request path here, but we assume that the length of an unspecified
// Cookies with unspecified path default to the path of the request. We don't // path is longer than any specified path (i.e. pathless cookies come first),
// know the request path here, but we assume that the length of an unspecified // because setting cookies with a path longer than the request path is of
// path is longer than any specified path (i.e. pathless cookies come first), // limited use.
// because setting cookies with a path longer than the request path is of int len1 = path1 == null ? Integer.MAX_VALUE : path1.length();
// limited use. int len2 = path2 == null ? Integer.MAX_VALUE : path2.length();
int len1 = path1 == null ? Integer.MAX_VALUE : path1.length(); int diff = len2 - len1;
int len2 = path2 == null ? Integer.MAX_VALUE : path2.length(); if (diff != 0) {
int diff = len2 - len1; return diff;
if (diff != 0) {
return diff;
}
// Rely on Java's sort stability to retain creation order in cases where
// cookies have same path length.
return -1;
} }
// Rely on Java's sort stability to retain creation order in cases where
// cookies have same path length.
return -1;
}; };
/** /**

View File

@ -174,26 +174,23 @@ public abstract class WebSocketClientHandshaker {
} }
} }
channel.writeAndFlush(request).addListener(new ChannelFutureListener() { channel.writeAndFlush(request).addListener((ChannelFutureListener) future -> {
@Override if (future.isSuccess()) {
public void operationComplete(ChannelFuture future) { ChannelPipeline p = future.channel().pipeline();
if (future.isSuccess()) { ChannelHandlerContext ctx = p.context(HttpRequestEncoder.class);
ChannelPipeline p = future.channel().pipeline(); if (ctx == null) {
ChannelHandlerContext ctx = p.context(HttpRequestEncoder.class); ctx = p.context(HttpClientCodec.class);
if (ctx == null) {
ctx = p.context(HttpClientCodec.class);
}
if (ctx == null) {
promise.setFailure(new IllegalStateException("ChannelPipeline does not contain " +
"a HttpRequestEncoder or HttpClientCodec"));
return;
}
p.addAfter(ctx.name(), "ws-encoder", newWebSocketEncoder());
promise.setSuccess();
} else {
promise.setFailure(future.cause());
} }
if (ctx == null) {
promise.setFailure(new IllegalStateException("ChannelPipeline does not contain " +
"a HttpRequestEncoder or HttpClientCodec"));
return;
}
p.addAfter(ctx.name(), "ws-encoder", newWebSocketEncoder());
promise.setSuccess();
} else {
promise.setFailure(future.cause());
} }
}); });
return promise; return promise;
@ -274,12 +271,7 @@ public abstract class WebSocketClientHandshaker {
// Delay the removal of the decoder so the user can setup the pipeline if needed to handle // Delay the removal of the decoder so the user can setup the pipeline if needed to handle
// WebSocketFrame messages. // WebSocketFrame messages.
// See https://github.com/netty/netty/issues/4533 // See https://github.com/netty/netty/issues/4533
channel.eventLoop().execute(new Runnable() { channel.eventLoop().execute(() -> p.remove(codec));
@Override
public void run() {
p.remove(codec);
}
});
} else { } else {
if (p.get(HttpRequestEncoder.class) != null) { if (p.get(HttpRequestEncoder.class) != null) {
// Remove the encoder part of the codec as the user may start writing frames after this method returns. // Remove the encoder part of the codec as the user may start writing frames after this method returns.
@ -291,12 +283,7 @@ public abstract class WebSocketClientHandshaker {
// Delay the removal of the decoder so the user can setup the pipeline if needed to handle // Delay the removal of the decoder so the user can setup the pipeline if needed to handle
// WebSocketFrame messages. // WebSocketFrame messages.
// See https://github.com/netty/netty/issues/4533 // See https://github.com/netty/netty/issues/4533
channel.eventLoop().execute(new Runnable() { channel.eventLoop().execute(() -> p.remove(context.handler()));
@Override
public void run() {
p.remove(context.handler());
}
});
} }
} }

View File

@ -31,15 +31,12 @@ class WebSocketClientProtocolHandshakeHandler extends ChannelInboundHandlerAdapt
@Override @Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception { public void channelActive(final ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx); super.channelActive(ctx);
handshaker.handshake(ctx.channel()).addListener(new ChannelFutureListener() { handshaker.handshake(ctx.channel()).addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { ctx.fireExceptionCaught(future.cause());
if (!future.isSuccess()) { } else {
ctx.fireExceptionCaught(future.cause()); ctx.fireUserEventTriggered(
} else { WebSocketClientProtocolHandler.ClientHandshakeStateEvent.HANDSHAKE_ISSUED);
ctx.fireUserEventTriggered(
WebSocketClientProtocolHandler.ClientHandshakeStateEvent.HANDSHAKE_ISSUED);
}
} }
}); });
} }

View File

@ -191,16 +191,13 @@ public abstract class WebSocketServerHandshaker {
encoderName = p.context(HttpResponseEncoder.class).name(); encoderName = p.context(HttpResponseEncoder.class).name();
p.addBefore(encoderName, "wsencoder", newWebSocketEncoder()); p.addBefore(encoderName, "wsencoder", newWebSocketEncoder());
} }
channel.writeAndFlush(response).addListener(new ChannelFutureListener() { channel.writeAndFlush(response).addListener((ChannelFutureListener) future -> {
@Override if (future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { ChannelPipeline p1 = future.channel().pipeline();
if (future.isSuccess()) { p1.remove(encoderName);
ChannelPipeline p = future.channel().pipeline(); promise.setSuccess();
p.remove(encoderName); } else {
promise.setSuccess(); promise.setFailure(future.cause());
} else {
promise.setFailure(future.cause());
}
} }
}); });
return promise; return promise;

View File

@ -81,19 +81,16 @@ class WebSocketServerProtocolHandshakeHandler extends ChannelInboundHandlerAdapt
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
} else { } else {
final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req); final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req);
handshakeFuture.addListener(new ChannelFutureListener() { handshakeFuture.addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { ctx.fireExceptionCaught(future.cause());
if (!future.isSuccess()) { } else {
ctx.fireExceptionCaught(future.cause()); // Kept for compatibility
} else { ctx.fireUserEventTriggered(
// Kept for compatibility WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE);
ctx.fireUserEventTriggered( ctx.fireUserEventTriggered(
WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE); new WebSocketServerProtocolHandler.HandshakeComplete(
ctx.fireUserEventTriggered( req.uri(), req.headers(), handshaker.selectedSubprotocol()));
new WebSocketServerProtocolHandler.HandshakeComplete(
req.uri(), req.headers(), handshaker.selectedSubprotocol()));
}
} }
}); });
WebSocketServerProtocolHandler.setHandshaker(ctx.channel(), handshaker); WebSocketServerProtocolHandler.setHandshaker(ctx.channel(), handshaker);

View File

@ -115,20 +115,17 @@ public class WebSocketServerExtensionHandler extends ChannelDuplexHandler {
extensionData.name(), extensionData.parameters()); extensionData.name(), extensionData.parameters());
} }
promise.addListener(new ChannelFutureListener() { promise.addListener((ChannelFutureListener) future -> {
@Override if (future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { for (WebSocketServerExtension extension : validExtensions) {
if (future.isSuccess()) { WebSocketExtensionDecoder decoder = extension.newExtensionDecoder();
for (WebSocketServerExtension extension : validExtensions) { WebSocketExtensionEncoder encoder = extension.newExtensionEncoder();
WebSocketExtensionDecoder decoder = extension.newExtensionDecoder(); ctx.pipeline().addAfter(ctx.name(), decoder.getClass().getName(), decoder);
WebSocketExtensionEncoder encoder = extension.newExtensionEncoder(); ctx.pipeline().addAfter(ctx.name(), encoder.getClass().getName(), encoder);
ctx.pipeline().addAfter(ctx.name(), decoder.getClass().getName(), decoder);
ctx.pipeline().addAfter(ctx.name(), encoder.getClass().getName(), encoder);
}
} }
ctx.pipeline().remove(ctx.name());
} }
ctx.pipeline().remove(ctx.name());
}); });
if (headerValue != null) { if (headerValue != null) {

View File

@ -27,12 +27,7 @@ import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER; import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
public class DefaultSpdyHeaders extends DefaultHeaders<CharSequence, CharSequence, SpdyHeaders> implements SpdyHeaders { public class DefaultSpdyHeaders extends DefaultHeaders<CharSequence, CharSequence, SpdyHeaders> implements SpdyHeaders {
private static final NameValidator<CharSequence> SpdyNameValidator = new NameValidator<CharSequence>() { private static final NameValidator<CharSequence> SpdyNameValidator = SpdyCodecUtil::validateHeaderName;
@Override
public void validateName(CharSequence name) {
SpdyCodecUtil.validateHeaderName(name);
}
};
public DefaultSpdyHeaders() { public DefaultSpdyHeaders() {
this(true); this(true);

View File

@ -109,12 +109,9 @@ public class SpdyFrameCodec extends ByteToMessageDecoder
public void handlerAdded(ChannelHandlerContext ctx) throws Exception { public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx); super.handlerAdded(ctx);
this.ctx = ctx; this.ctx = ctx;
ctx.channel().closeFuture().addListener(new ChannelFutureListener() { ctx.channel().closeFuture().addListener((ChannelFutureListener) future -> {
@Override spdyHeaderBlockDecoder.end();
public void operationComplete(ChannelFuture future) throws Exception { spdyHeaderBlockEncoder.end();
spdyHeaderBlockDecoder.end();
spdyHeaderBlockEncoder.end();
}
}); });
} }

View File

@ -504,12 +504,9 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the session on write failures that leave the transfer window in a corrupt state. // Close the session on write failures that leave the transfer window in a corrupt state.
final ChannelHandlerContext context = ctx; final ChannelHandlerContext context = ctx;
ctx.write(partialDataFrame).addListener(new ChannelFutureListener() { ctx.write(partialDataFrame).addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR);
if (!future.isSuccess()) {
issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR);
}
} }
}); });
return; return;
@ -521,12 +518,9 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the session on write failures that leave the transfer window in a corrupt state. // Close the session on write failures that leave the transfer window in a corrupt state.
final ChannelHandlerContext context = ctx; final ChannelHandlerContext context = ctx;
promise.addListener(new ChannelFutureListener() { promise.addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR);
if (!future.isSuccess()) {
issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR);
}
} }
}); });
} }
@ -781,12 +775,9 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the session on write failures that leave the transfer window in a corrupt state. // Close the session on write failures that leave the transfer window in a corrupt state.
ctx.writeAndFlush(partialDataFrame).addListener(new ChannelFutureListener() { ctx.writeAndFlush(partialDataFrame).addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR);
if (!future.isSuccess()) {
issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR);
}
} }
}); });
} else { } else {
@ -802,12 +793,9 @@ public class SpdySessionHandler extends ChannelDuplexHandler {
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the session on write failures that leave the transfer window in a corrupt state. // Close the session on write failures that leave the transfer window in a corrupt state.
ctx.writeAndFlush(spdyDataFrame, pendingWrite.promise).addListener(new ChannelFutureListener() { ctx.writeAndFlush(spdyDataFrame, pendingWrite.promise).addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR);
if (!future.isSuccess()) {
issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR);
}
} }
}); });
} }

View File

@ -147,22 +147,16 @@ public class HttpClientCodecTest {
sChannel.writeAndFlush(Unpooled.wrappedBuffer(("HTTP/1.0 200 OK\r\n" + sChannel.writeAndFlush(Unpooled.wrappedBuffer(("HTTP/1.0 200 OK\r\n" +
"Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n" + "Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n" +
"Content-Type: text/html\r\n\r\n").getBytes(CharsetUtil.ISO_8859_1))) "Content-Type: text/html\r\n\r\n").getBytes(CharsetUtil.ISO_8859_1)))
.addListener(new ChannelFutureListener() { .addListener((ChannelFutureListener) future -> {
@Override assertTrue(future.isSuccess());
public void operationComplete(ChannelFuture future) throws Exception { sChannel.writeAndFlush(Unpooled.wrappedBuffer(
assertTrue(future.isSuccess()); "<html><body>hello half closed!</body></html>\r\n"
sChannel.writeAndFlush(Unpooled.wrappedBuffer( .getBytes(CharsetUtil.ISO_8859_1)))
"<html><body>hello half closed!</body></html>\r\n" .addListener((ChannelFutureListener) future1 -> {
.getBytes(CharsetUtil.ISO_8859_1))) assertTrue(future1.isSuccess());
.addListener(new ChannelFutureListener() { sChannel.shutdownOutput();
@Override });
public void operationComplete(ChannelFuture future) throws Exception {
assertTrue(future.isSuccess());
sChannel.shutdownOutput();
}
}); });
}
});
} }
}); });
serverChannelLatch.countDown(); serverChannelLatch.countDown();

View File

@ -64,12 +64,7 @@ public class HttpServerUpgradeHandlerTest {
@Test @Test
public void upgradesPipelineInSameMethodInvocation() { public void upgradesPipelineInSameMethodInvocation() {
final HttpServerCodec httpServerCodec = new HttpServerCodec(); final HttpServerCodec httpServerCodec = new HttpServerCodec();
final UpgradeCodecFactory factory = new UpgradeCodecFactory() { final UpgradeCodecFactory factory = protocol -> new TestUpgradeCodec();
@Override
public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
return new TestUpgradeCodec();
}
};
ChannelHandler testInStackFrame = new ChannelDuplexHandler() { ChannelHandler testInStackFrame = new ChannelDuplexHandler() {
// marker boolean to signal that we're in the `channelRead` method // marker boolean to signal that we're in the `channelRead` method
@ -102,18 +97,8 @@ public class HttpServerUpgradeHandlerTest {
// make sure the pipeline was reformed irrespective of the flush completing. // make sure the pipeline was reformed irrespective of the flush completing.
assertTrue(inReadCall); assertTrue(inReadCall);
writeUpgradeMessage = true; writeUpgradeMessage = true;
ctx.channel().eventLoop().execute(new Runnable() { ctx.channel().eventLoop().execute(() -> ctx.write(msg, promise));
@Override promise.addListener((ChannelFutureListener) future -> writeFlushed = true);
public void run() {
ctx.write(msg, promise);
}
});
promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
writeFlushed = true;
}
});
} }
}; };

View File

@ -186,12 +186,7 @@ public class CorsHandlerTest {
@Test @Test
public void preflightRequestWithValueGenerator() { public void preflightRequestWithValueGenerator() {
final CorsConfig config = forOrigin("http://localhost:8888") final CorsConfig config = forOrigin("http://localhost:8888")
.preflightResponseHeader("GenHeader", new Callable<String>() { .preflightResponseHeader("GenHeader", () -> "generatedValue").build();
@Override
public String call() throws Exception {
return "generatedValue";
}
}).build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1"); final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertThat(response.headers().get(of("GenHeader")), equalTo("generatedValue")); assertThat(response.headers().get(of("GenHeader")), equalTo("generatedValue"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString())); assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));

View File

@ -277,14 +277,11 @@ public class DefaultHttp2Connection implements Http2Connection {
private void closeStreamsGreaterThanLastKnownStreamId(final int lastKnownStream, private void closeStreamsGreaterThanLastKnownStreamId(final int lastKnownStream,
final DefaultEndpoint<?> endpoint) throws Http2Exception { final DefaultEndpoint<?> endpoint) throws Http2Exception {
forEachActiveStream(new Http2StreamVisitor() { forEachActiveStream(stream -> {
@Override if (stream.id() > lastKnownStream && endpoint.isValidStreamId(stream.id())) {
public boolean visit(Http2Stream stream) { stream.close();
if (stream.id() > lastKnownStream && endpoint.isValidStreamId(stream.id())) {
stream.close();
}
return true;
} }
return true;
}); });
} }
@ -942,12 +939,7 @@ public class DefaultHttp2Connection implements Http2Connection {
if (allowModifications()) { if (allowModifications()) {
addToActiveStreams(stream); addToActiveStreams(stream);
} else { } else {
pendingEvents.add(new Event() { pendingEvents.add(() -> addToActiveStreams(stream));
@Override
public void process() {
addToActiveStreams(stream);
}
});
} }
} }
@ -955,12 +947,7 @@ public class DefaultHttp2Connection implements Http2Connection {
if (allowModifications() || itr != null) { if (allowModifications() || itr != null) {
removeFromActiveStreams(stream, itr); removeFromActiveStreams(stream, itr);
} else { } else {
pendingEvents.add(new Event() { pendingEvents.add(() -> removeFromActiveStreams(stream, itr));
@Override
public void process() {
removeFromActiveStreams(stream, itr);
}
});
} }
} }

View File

@ -463,13 +463,10 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder {
} }
private void notifyLifecycleManagerOnError(ChannelFuture future, final ChannelHandlerContext ctx) { private void notifyLifecycleManagerOnError(ChannelFuture future, final ChannelHandlerContext ctx) {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> {
@Override Throwable cause = future1.cause();
public void operationComplete(ChannelFuture future) throws Exception { if (cause != null) {
Throwable cause = future.cause(); lifecycleManager.onError(ctx, true, cause);
if (cause != null) {
lifecycleManager.onError(ctx, true, cause);
}
} }
}); });
} }

View File

@ -31,43 +31,35 @@ import static io.netty.util.AsciiString.isUpperCase;
@UnstableApi @UnstableApi
public class DefaultHttp2Headers public class DefaultHttp2Headers
extends DefaultHeaders<CharSequence, CharSequence, Http2Headers> implements Http2Headers { extends DefaultHeaders<CharSequence, CharSequence, Http2Headers> implements Http2Headers {
private static final ByteProcessor HTTP2_NAME_VALIDATOR_PROCESSOR = new ByteProcessor() { private static final ByteProcessor HTTP2_NAME_VALIDATOR_PROCESSOR = value -> !isUpperCase(value);
@Override static final NameValidator<CharSequence> HTTP2_NAME_VALIDATOR = name -> {
public boolean process(byte value) { if (name == null || name.length() == 0) {
return !isUpperCase(value); PlatformDependent.throwException(connectionError(PROTOCOL_ERROR,
"empty headers are not allowed [%s]", name));
} }
}; if (name instanceof AsciiString) {
static final NameValidator<CharSequence> HTTP2_NAME_VALIDATOR = new NameValidator<CharSequence>() { final int index;
@Override try {
public void validateName(CharSequence name) { index = ((AsciiString) name).forEachByte(HTTP2_NAME_VALIDATOR_PROCESSOR);
if (name == null || name.length() == 0) { } catch (Http2Exception e) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR, PlatformDependent.throwException(e);
"empty headers are not allowed [%s]", name)); return;
} catch (Throwable t) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR, t,
"unexpected error. invalid header name [%s]", name));
return;
} }
if (name instanceof AsciiString) {
final int index;
try {
index = ((AsciiString) name).forEachByte(HTTP2_NAME_VALIDATOR_PROCESSOR);
} catch (Http2Exception e) {
PlatformDependent.throwException(e);
return;
} catch (Throwable t) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR, t,
"unexpected error. invalid header name [%s]", name));
return;
}
if (index != -1) { if (index != -1) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR,
"invalid header name [%s]", name));
}
} else {
for (int i = 0; i < name.length(); ++i) {
if (isUpperCase(name.charAt(i))) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR, PlatformDependent.throwException(connectionError(PROTOCOL_ERROR,
"invalid header name [%s]", name)); "invalid header name [%s]", name));
} }
} else {
for (int i = 0; i < name.length(); ++i) {
if (isUpperCase(name.charAt(i))) {
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR,
"invalid header name [%s]", name));
}
}
} }
} }
}; };

View File

@ -641,12 +641,9 @@ public class DefaultHttp2RemoteFlowController implements Http2RemoteFlowControll
final int delta = newWindowSize - initialWindowSize; final int delta = newWindowSize - initialWindowSize;
initialWindowSize = newWindowSize; initialWindowSize = newWindowSize;
connection.forEachActiveStream(new Http2StreamVisitor() { connection.forEachActiveStream(stream -> {
@Override state(stream).incrementStreamWindow(delta);
public boolean visit(Http2Stream stream) throws Http2Exception { return true;
state(stream).incrementStreamWindow(delta);
return true;
}
}); });
if (delta > 0 && isChannelWritable()) { if (delta > 0 && isChannelWritable()) {

View File

@ -606,12 +606,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
if (future.isDone()) { if (future.isDone()) {
checkCloseConnection(future); checkCloseConnection(future);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) this::checkCloseConnection);
@Override
public void operationComplete(ChannelFuture future) throws Exception {
checkCloseConnection(future);
}
});
} }
} }
@ -750,12 +745,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
if (future.isDone()) { if (future.isDone()) {
closeConnectionOnError(ctx, future); closeConnectionOnError(ctx, future);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> closeConnectionOnError(ctx, future1));
@Override
public void operationComplete(ChannelFuture future) throws Exception {
closeConnectionOnError(ctx, future);
}
});
} }
return future; return future;
} }
@ -795,12 +785,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
if (future.isDone()) { if (future.isDone()) {
processRstStreamWriteResult(ctx, stream, future); processRstStreamWriteResult(ctx, stream, future);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> processRstStreamWriteResult(ctx, stream, future1));
@Override
public void operationComplete(ChannelFuture future) throws Exception {
processRstStreamWriteResult(ctx, stream, future);
}
});
} }
return future; return future;
@ -831,12 +816,8 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
if (future.isDone()) { if (future.isDone()) {
processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future); processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 ->
@Override processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future1));
public void operationComplete(ChannelFuture future) throws Exception {
processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future);
}
});
} }
return future; return future;
@ -938,11 +919,8 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
long timeout, TimeUnit unit) { long timeout, TimeUnit unit) {
this.ctx = ctx; this.ctx = ctx;
this.promise = promise; this.promise = promise;
timeoutTask = ctx.executor().schedule(new Runnable() { timeoutTask = ctx.executor().schedule(() -> {
@Override ctx.close(promise);
public void run() {
ctx.close(promise);
}
}, timeout, unit); }, timeout, unit);
} }

View File

@ -183,15 +183,12 @@ public class Http2FrameCodec extends Http2ConnectionHandler {
final void forEachActiveStream(final Http2FrameStreamVisitor streamVisitor) throws Http2Exception { final void forEachActiveStream(final Http2FrameStreamVisitor streamVisitor) throws Http2Exception {
assert ctx.executor().inEventLoop(); assert ctx.executor().inEventLoop();
connection().forEachActiveStream(new Http2StreamVisitor() { connection().forEachActiveStream(stream -> {
@Override try {
public boolean visit(Http2Stream stream) { return streamVisitor.visit((Http2FrameStream) stream.getProperty(streamKey));
try { } catch (Throwable cause) {
return streamVisitor.visit((Http2FrameStream) stream.getProperty(streamKey)); onError(ctx, false, cause);
} catch (Throwable cause) { return false;
onError(ctx, false, cause);
return false;
}
} }
}); });
} }
@ -381,13 +378,10 @@ public class Http2FrameCodec extends Http2ConnectionHandler {
} else { } else {
numBufferedStreams++; numBufferedStreams++;
writePromise.addListener(new ChannelFutureListener() { writePromise.addListener((ChannelFutureListener) future -> {
@Override numBufferedStreams--;
public void operationComplete(ChannelFuture future) throws Exception {
numBufferedStreams--;
notifyHeaderWritePromise(future, promise); notifyHeaderWritePromise(future, promise);
}
}); });
} }
} }

View File

@ -90,20 +90,10 @@ public interface Http2HeadersEncoder {
/** /**
* Always return {@code false} for {@link SensitivityDetector#isSensitive(CharSequence, CharSequence)}. * Always return {@code false} for {@link SensitivityDetector#isSensitive(CharSequence, CharSequence)}.
*/ */
SensitivityDetector NEVER_SENSITIVE = new SensitivityDetector() { SensitivityDetector NEVER_SENSITIVE = (name, value) -> false;
@Override
public boolean isSensitive(CharSequence name, CharSequence value) {
return false;
}
};
/** /**
* Always return {@code true} for {@link SensitivityDetector#isSensitive(CharSequence, CharSequence)}. * Always return {@code true} for {@link SensitivityDetector#isSensitive(CharSequence, CharSequence)}.
*/ */
SensitivityDetector ALWAYS_SENSITIVE = new SensitivityDetector() { SensitivityDetector ALWAYS_SENSITIVE = (name, value) -> true;
@Override
public boolean isSensitive(CharSequence name, CharSequence value) {
return true;
}
};
} }

View File

@ -108,12 +108,7 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultHttp2StreamChannel.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultHttp2StreamChannel.class);
private static final ChannelFutureListener CHILD_CHANNEL_REGISTRATION_LISTENER = new ChannelFutureListener() { private static final ChannelFutureListener CHILD_CHANNEL_REGISTRATION_LISTENER = Http2MultiplexCodec::registerDone;
@Override
public void operationComplete(ChannelFuture future) {
registerDone(future);
}
};
private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16); private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
@ -131,15 +126,10 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
static final FlowControlledFrameSizeEstimator INSTANCE = new FlowControlledFrameSizeEstimator(); static final FlowControlledFrameSizeEstimator INSTANCE = new FlowControlledFrameSizeEstimator();
static final MessageSizeEstimator.Handle HANDLE_INSTANCE = new MessageSizeEstimator.Handle() { static final MessageSizeEstimator.Handle HANDLE_INSTANCE = msg -> msg instanceof Http2DataFrame ?
@Override // Guard against overflow.
public int size(Object msg) { (int) min(Integer.MAX_VALUE, ((Http2DataFrame) msg).initialFlowControlledBytes() +
return msg instanceof Http2DataFrame ? (long) MIN_HTTP2_FRAME_SIZE) : MIN_HTTP2_FRAME_SIZE;
// Guard against overflow.
(int) min(Integer.MAX_VALUE, ((Http2DataFrame) msg).initialFlowControlledBytes() +
(long) MIN_HTTP2_FRAME_SIZE) : MIN_HTTP2_FRAME_SIZE;
}
};
@Override @Override
public Handle newHandle() { public Handle newHandle() {
@ -361,16 +351,13 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
private void onHttp2GoAwayFrame(ChannelHandlerContext ctx, final Http2GoAwayFrame goAwayFrame) { private void onHttp2GoAwayFrame(ChannelHandlerContext ctx, final Http2GoAwayFrame goAwayFrame) {
try { try {
forEachActiveStream(new Http2FrameStreamVisitor() { forEachActiveStream(stream -> {
@Override final int streamId = stream.id();
public boolean visit(Http2FrameStream stream) { final DefaultHttp2StreamChannel childChannel = ((Http2MultiplexCodecStream) stream).channel;
final int streamId = stream.id(); if (streamId > goAwayFrame.lastStreamId() && connection().local().isValidStreamId(streamId)) {
final DefaultHttp2StreamChannel childChannel = ((Http2MultiplexCodecStream) stream).channel; childChannel.pipeline().fireUserEventTriggered(goAwayFrame.retainedDuplicate());
if (streamId > goAwayFrame.lastStreamId() && connection().local().isValidStreamId(streamId)) {
childChannel.pipeline().fireUserEventTriggered(goAwayFrame.retainedDuplicate());
}
return true;
} }
return true;
}); });
} catch (Http2Exception e) { } catch (Http2Exception e) {
ctx.fireExceptionCaught(e); ctx.fireExceptionCaught(e);
@ -890,12 +877,7 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
promise.setSuccess(); promise.setSuccess();
} else if (!(promise instanceof VoidChannelPromise)) { // Only needed if no VoidChannelPromise. } else if (!(promise instanceof VoidChannelPromise)) { // Only needed if no VoidChannelPromise.
// This means close() was called before so we just register a listener and return // This means close() was called before so we just register a listener and return
closePromise.addListener(new ChannelFutureListener() { closePromise.addListener((ChannelFutureListener) future -> promise.setSuccess());
@Override
public void operationComplete(ChannelFuture future) {
promise.setSuccess();
}
});
} }
return; return;
} }
@ -959,20 +941,17 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
// //
// See: // See:
// https://github.com/netty/netty/issues/4435 // https://github.com/netty/netty/issues/4435
invokeLater(new Runnable() { invokeLater(() -> {
@Override if (fireChannelInactive) {
public void run() { pipeline.fireChannelInactive();
if (fireChannelInactive) {
pipeline.fireChannelInactive();
}
// The user can fire `deregister` events multiple times but we only want to fire the pipeline
// event if the channel was actually registered.
if (registered) {
registered = false;
pipeline.fireChannelUnregistered();
}
safeSetSuccess(promise);
} }
// The user can fire `deregister` events multiple times but we only want to fire the pipeline
// event if the channel was actually registered.
if (registered) {
registered = false;
pipeline.fireChannelUnregistered();
}
safeSetSuccess(promise);
}); });
} }
@ -1127,12 +1106,8 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
if (future.isDone()) { if (future.isDone()) {
firstWriteComplete(future, promise); firstWriteComplete(future, promise);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future12 ->
@Override firstWriteComplete(future12, promise));
public void operationComplete(ChannelFuture future) {
firstWriteComplete(future, promise);
}
});
} }
return; return;
} }
@ -1149,12 +1124,7 @@ public class Http2MultiplexCodec extends Http2FrameCodec {
if (future.isDone()) { if (future.isDone()) {
writeComplete(future, promise); writeComplete(future, promise);
} else { } else {
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> writeComplete(future1, promise));
@Override
public void operationComplete(ChannelFuture future) {
writeComplete(future, promise);
}
});
} }
} catch (Throwable t) { } catch (Throwable t) {
promise.tryFailure(t); promise.tryFailure(t);

View File

@ -118,12 +118,7 @@ public final class Http2StreamChannelBootstrap {
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
open0(ctx, promise); open0(ctx, promise);
} else { } else {
executor.execute(new Runnable() { executor.execute(() -> open0(ctx, promise));
@Override
public void run() {
open0(ctx, promise);
}
});
} }
} }
return promise; return promise;
@ -141,22 +136,19 @@ public final class Http2StreamChannelBootstrap {
} }
ChannelFuture future = streamChannel.register(); ChannelFuture future = streamChannel.register();
future.addListener(new ChannelFutureListener() { future.addListener((ChannelFutureListener) future1 -> {
@Override if (future1.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { promise.setSuccess(streamChannel);
if (future.isSuccess()) { } else if (future1.isCancelled()) {
promise.setSuccess(streamChannel); promise.cancel(false);
} else if (future.isCancelled()) { } else {
promise.cancel(false); if (streamChannel.isRegistered()) {
streamChannel.close();
} else { } else {
if (streamChannel.isRegistered()) { streamChannel.unsafe().closeForcibly();
streamChannel.close();
} else {
streamChannel.unsafe().closeForcibly();
}
promise.setFailure(future.cause());
} }
promise.setFailure(future1.cause());
} }
}); });
} }

View File

@ -35,21 +35,18 @@ abstract class AbstractWeightedFairQueueByteDistributorDependencyTest {
} }
Answer<Void> writeAnswer(final boolean closeIfNoFrame) { Answer<Void> writeAnswer(final boolean closeIfNoFrame) {
return new Answer<Void>() { return in -> {
@Override Http2Stream stream = in.getArgument(0);
public Void answer(InvocationOnMock in) throws Throwable { int numBytes = in.getArgument(1);
Http2Stream stream = in.getArgument(0); TestStreamByteDistributorStreamState state = stateMap.get(stream.id());
int numBytes = in.getArgument(1); state.pendingBytes -= numBytes;
TestStreamByteDistributorStreamState state = stateMap.get(stream.id()); state.hasFrame = state.pendingBytes > 0;
state.pendingBytes -= numBytes; state.isWriteAllowed = state.hasFrame;
state.hasFrame = state.pendingBytes > 0; if (closeIfNoFrame && !state.hasFrame) {
state.isWriteAllowed = state.hasFrame; stream.close();
if (closeIfNoFrame && !state.hasFrame) {
stream.close();
}
distributor.updateStreamableBytes(state);
return null;
} }
distributor.updateStreamableBytes(state);
return null;
}; };
} }

View File

@ -63,12 +63,7 @@ public class CleartextHttp2ServerUpgradeHandlerTest {
http2ConnectionHandler = new Http2ConnectionHandlerBuilder() http2ConnectionHandler = new Http2ConnectionHandlerBuilder()
.frameListener(frameListener).build(); .frameListener(frameListener).build();
UpgradeCodecFactory upgradeCodecFactory = new UpgradeCodecFactory() { UpgradeCodecFactory upgradeCodecFactory = protocol -> new Http2ServerUpgradeCodec(http2ConnectionHandler);
@Override
public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
return new Http2ServerUpgradeCodec(http2ConnectionHandler);
}
};
userEvents = new ArrayList<>(); userEvents = new ArrayList<>();
@ -205,12 +200,7 @@ public class CleartextHttp2ServerUpgradeHandlerTest {
protected void initChannel(Channel ch) throws Exception { protected void initChannel(Channel ch) throws Exception {
} }
}).build(); }).build();
UpgradeCodecFactory upgradeCodecFactory = new UpgradeCodecFactory() { UpgradeCodecFactory upgradeCodecFactory = protocol -> new Http2ServerUpgradeCodec(http2Codec);
@Override
public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
return new Http2ServerUpgradeCodec(http2Codec);
}
};
http2ConnectionHandler = http2Codec; http2ConnectionHandler = http2Codec;
userEvents = new ArrayList<>(); userEvents = new ArrayList<>();

View File

@ -92,24 +92,18 @@ public class DataCompressionHttp2Test {
@Before @Before
public void setup() throws InterruptedException, Http2Exception { public void setup() throws InterruptedException, Http2Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
doAnswer(new Answer<Void>() { doAnswer(invocation -> {
@Override if (invocation.getArgument(4)) {
public Void answer(InvocationOnMock invocation) throws Throwable { serverConnection.stream((Integer) invocation.getArgument(1)).close();
if (invocation.getArgument(4)) {
serverConnection.stream((Integer) invocation.getArgument(1)).close();
}
return null;
} }
return null;
}).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class), }).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class),
anyInt(), anyBoolean()); anyInt(), anyBoolean());
doAnswer(new Answer<Void>() { doAnswer(invocation -> {
@Override if (invocation.getArgument(7)) {
public Void answer(InvocationOnMock invocation) throws Throwable { serverConnection.stream((Integer) invocation.getArgument(1)).close();
if (invocation.getArgument(7)) {
serverConnection.stream((Integer) invocation.getArgument(1)).close();
}
return null;
} }
return null;
}).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class), }).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class),
anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean()); anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean());
} }
@ -148,12 +142,9 @@ public class DataCompressionHttp2Test {
final Http2Headers headers = new DefaultHttp2Headers().method(GET).path(PATH) final Http2Headers headers = new DefaultHttp2Headers().method(GET).path(PATH)
.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP); .set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientHandler.flush(ctxClient());
clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, true, newPromiseClient());
clientHandler.flush(ctxClient());
}
}); });
awaitServer(); awaitServer();
verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0),
@ -169,13 +160,10 @@ public class DataCompressionHttp2Test {
final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH) final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH)
.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP); .set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient()); clientHandler.flush(ctxClient());
clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientHandler.flush(ctxClient());
}
}); });
awaitServer(); awaitServer();
assertEquals(text, serverOut.toString(CharsetUtil.UTF_8.name())); assertEquals(text, serverOut.toString(CharsetUtil.UTF_8.name()));
@ -193,13 +181,10 @@ public class DataCompressionHttp2Test {
final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH) final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH)
.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP); .set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient()); clientHandler.flush(ctxClient());
clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientHandler.flush(ctxClient());
}
}); });
awaitServer(); awaitServer();
assertEquals(text, serverOut.toString(CharsetUtil.UTF_8.name())); assertEquals(text, serverOut.toString(CharsetUtil.UTF_8.name()));
@ -219,14 +204,11 @@ public class DataCompressionHttp2Test {
final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH) final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH)
.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP); .set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientEncoder.writeData(ctxClient(), 3, data1.retain(), 0, false, newPromiseClient());
clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient()); clientEncoder.writeData(ctxClient(), 3, data2.retain(), 0, true, newPromiseClient());
clientEncoder.writeData(ctxClient(), 3, data1.retain(), 0, false, newPromiseClient()); clientHandler.flush(ctxClient());
clientEncoder.writeData(ctxClient(), 3, data2.retain(), 0, true, newPromiseClient());
clientHandler.flush(ctxClient());
}
}); });
awaitServer(); awaitServer();
assertEquals(text1 + text2, serverOut.toString(CharsetUtil.UTF_8.name())); assertEquals(text1 + text2, serverOut.toString(CharsetUtil.UTF_8.name()));
@ -247,13 +229,10 @@ public class DataCompressionHttp2Test {
final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH) final Http2Headers headers = new DefaultHttp2Headers().method(POST).path(PATH)
.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.DEFLATE); .set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.DEFLATE);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientEncoder.writeHeaders(ctxClient(), 3, headers, 0, false, newPromiseClient()); clientHandler.flush(ctxClient());
clientEncoder.writeData(ctxClient(), 3, data.retain(), 0, true, newPromiseClient());
clientHandler.flush(ctxClient());
}
}); });
awaitServer(); awaitServer();
assertEquals(data.readerIndex(0).toString(CharsetUtil.UTF_8), assertEquals(data.readerIndex(0).toString(CharsetUtil.UTF_8),
@ -281,20 +260,17 @@ public class DataCompressionHttp2Test {
} }
}); });
doAnswer(new Answer<Integer>() { doAnswer(in -> {
@Override ByteBuf buf = (ByteBuf) in.getArguments()[2];
public Integer answer(InvocationOnMock in) throws Throwable { int padding = (Integer) in.getArguments()[3];
ByteBuf buf = (ByteBuf) in.getArguments()[2]; int processedBytes = buf.readableBytes() + padding;
int padding = (Integer) in.getArguments()[3];
int processedBytes = buf.readableBytes() + padding;
buf.readBytes(serverOut, buf.readableBytes()); buf.readBytes(serverOut, buf.readableBytes());
if (in.getArgument(4)) { if (in.getArgument(4)) {
serverConnection.stream((Integer) in.getArgument(1)).close(); serverConnection.stream((Integer) in.getArgument(1)).close();
}
return processedBytes;
} }
return processedBytes;
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), anyInt(), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), anyInt(),
any(ByteBuf.class), anyInt(), anyBoolean()); any(ByteBuf.class), anyInt(), anyBoolean());

View File

@ -130,52 +130,38 @@ public class DefaultHttp2ConnectionDecoderTest {
when(stream.state()).thenReturn(OPEN); when(stream.state()).thenReturn(OPEN);
when(stream.open(anyBoolean())).thenReturn(stream); when(stream.open(anyBoolean())).thenReturn(stream);
when(pushStream.id()).thenReturn(PUSH_STREAM_ID); when(pushStream.id()).thenReturn(PUSH_STREAM_ID);
doAnswer(new Answer<Boolean>() { doAnswer((Answer<Boolean>) in ->
@Override (headersReceivedState.get() & STATE_RECV_HEADERS) != 0).when(stream).isHeadersReceived();
public Boolean answer(InvocationOnMock in) throws Throwable { doAnswer((Answer<Boolean>) in ->
return (headersReceivedState.get() & STATE_RECV_HEADERS) != 0; (headersReceivedState.get() & STATE_RECV_TRAILERS) != 0).when(stream).isTrailersReceived();
} doAnswer((Answer<Http2Stream>) in -> {
}).when(stream).isHeadersReceived(); boolean isInformational = in.getArgument(0);
doAnswer(new Answer<Boolean>() { if (isInformational) {
@Override
public Boolean answer(InvocationOnMock in) throws Throwable {
return (headersReceivedState.get() & STATE_RECV_TRAILERS) != 0;
}
}).when(stream).isTrailersReceived();
doAnswer(new Answer<Http2Stream>() {
@Override
public Http2Stream answer(InvocationOnMock in) throws Throwable {
boolean isInformational = in.getArgument(0);
if (isInformational) {
return stream;
}
for (;;) {
int current = headersReceivedState.get();
int next = current;
if ((current & STATE_RECV_HEADERS) != 0) {
if ((current & STATE_RECV_TRAILERS) != 0) {
throw new IllegalStateException("already sent headers!");
}
next |= STATE_RECV_TRAILERS;
} else {
next |= STATE_RECV_HEADERS;
}
if (headersReceivedState.compareAndSet(current, next)) {
break;
}
}
return stream; return stream;
} }
}).when(stream).headersReceived(anyBoolean()); for (;;) {
doAnswer(new Answer<Http2Stream>() { int current = headersReceivedState.get();
@Override int next = current;
public Http2Stream answer(InvocationOnMock in) throws Throwable { if ((current & STATE_RECV_HEADERS) != 0) {
Http2StreamVisitor visitor = in.getArgument(0); if ((current & STATE_RECV_TRAILERS) != 0) {
if (!visitor.visit(stream)) { throw new IllegalStateException("already sent headers!");
return stream; }
next |= STATE_RECV_TRAILERS;
} else {
next |= STATE_RECV_HEADERS;
}
if (headersReceivedState.compareAndSet(current, next)) {
break;
} }
return null;
} }
return stream;
}).when(stream).headersReceived(anyBoolean());
doAnswer((Answer<Http2Stream>) in -> {
Http2StreamVisitor visitor = in.getArgument(0);
if (!visitor.visit(stream)) {
return stream;
}
return null;
}).when(connection).forEachActiveStream(any(Http2StreamVisitor.class)); }).when(connection).forEachActiveStream(any(Http2StreamVisitor.class));
when(connection.stream(STREAM_ID)).thenReturn(stream); when(connection.stream(STREAM_ID)).thenReturn(stream);
when(connection.streamMayHaveExisted(STREAM_ID)).thenReturn(true); when(connection.streamMayHaveExisted(STREAM_ID)).thenReturn(true);
@ -391,30 +377,19 @@ public class DefaultHttp2ConnectionDecoderTest {
final ByteBuf data = dummyData(); final ByteBuf data = dummyData();
final int padding = 10; final int padding = 10;
final AtomicInteger unprocessed = new AtomicInteger(data.readableBytes() + padding); final AtomicInteger unprocessed = new AtomicInteger(data.readableBytes() + padding);
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) in -> unprocessed.get()).when(localFlow).unconsumedBytes(eq(stream));
@Override doAnswer((Answer<Void>) in -> {
public Integer answer(InvocationOnMock in) throws Throwable { int delta = (Integer) in.getArguments()[1];
return unprocessed.get(); int newValue = unprocessed.addAndGet(-delta);
} if (newValue < 0) {
}).when(localFlow).unconsumedBytes(eq(stream)); throw new RuntimeException("Returned too many bytes");
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock in) throws Throwable {
int delta = (Integer) in.getArguments()[1];
int newValue = unprocessed.addAndGet(-delta);
if (newValue < 0) {
throw new RuntimeException("Returned too many bytes");
}
return null;
} }
return null;
}).when(localFlow).consumeBytes(eq(stream), anyInt()); }).when(localFlow).consumeBytes(eq(stream), anyInt());
// When the listener callback is called, process a few bytes and then throw. // When the listener callback is called, process a few bytes and then throw.
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) in -> {
@Override localFlow.consumeBytes(stream, 4);
public Integer answer(InvocationOnMock in) throws Throwable { throw new RuntimeException("Fake Exception");
localFlow.consumeBytes(stream, 4);
throw new RuntimeException("Fake Exception");
}
}).when(listener).onDataRead(eq(ctx), eq(STREAM_ID), any(ByteBuf.class), eq(10), eq(true)); }).when(listener).onDataRead(eq(ctx), eq(STREAM_ID), any(ByteBuf.class), eq(10), eq(true));
try { try {
decode().onDataRead(ctx, STREAM_ID, data, padding, true); decode().onDataRead(ctx, STREAM_ID, data, padding, true);
@ -759,12 +734,8 @@ public class DefaultHttp2ConnectionDecoderTest {
} }
private void mockFlowControl(final int processedBytes) throws Http2Exception { private void mockFlowControl(final int processedBytes) throws Http2Exception {
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) invocation ->
@Override processedBytes).when(listener).onDataRead(any(ChannelHandlerContext.class), anyInt(),
public Integer answer(InvocationOnMock invocation) throws Throwable {
return processedBytes;
}
}).when(listener).onDataRead(any(ChannelHandlerContext.class), anyInt(),
any(ByteBuf.class), anyInt(), anyBoolean()); any(ByteBuf.class), anyInt(), anyBoolean());
} }

View File

@ -127,82 +127,55 @@ public class DefaultHttp2ConnectionEncoderTest {
when(channel.unsafe()).thenReturn(unsafe); when(channel.unsafe()).thenReturn(unsafe);
ChannelConfig config = new DefaultChannelConfig(channel); ChannelConfig config = new DefaultChannelConfig(channel);
when(channel.config()).thenReturn(config); when(channel.config()).thenReturn(config);
doAnswer(new Answer<ChannelFuture>() { doAnswer(in -> newPromise()
@Override .setFailure((Throwable) in.getArgument(0))).when(channel).newFailedFuture(any(Throwable.class));
public ChannelFuture answer(InvocationOnMock in) {
return newPromise().setFailure((Throwable) in.getArgument(0));
}
}).when(channel).newFailedFuture(any(Throwable.class));
when(writer.configuration()).thenReturn(writerConfig); when(writer.configuration()).thenReturn(writerConfig);
when(writerConfig.frameSizePolicy()).thenReturn(frameSizePolicy); when(writerConfig.frameSizePolicy()).thenReturn(frameSizePolicy);
when(frameSizePolicy.maxFrameSize()).thenReturn(64); when(frameSizePolicy.maxFrameSize()).thenReturn(64);
doAnswer(new Answer<ChannelFuture>() { doAnswer((Answer<ChannelFuture>) in -> ((ChannelPromise) in.getArguments()[2])
@Override .setSuccess()).when(writer).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class));
public ChannelFuture answer(InvocationOnMock in) throws Throwable { doAnswer((Answer<ChannelFuture>) in -> {
return ((ChannelPromise) in.getArguments()[2]).setSuccess(); ((ByteBuf) in.getArguments()[3]).release();
} return ((ChannelPromise) in.getArguments()[4]).setSuccess();
}).when(writer).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class));
doAnswer(new Answer<ChannelFuture>() {
@Override
public ChannelFuture answer(InvocationOnMock in) throws Throwable {
((ByteBuf) in.getArguments()[3]).release();
return ((ChannelPromise) in.getArguments()[4]).setSuccess();
}
}).when(writer).writeGoAway(eq(ctx), anyInt(), anyInt(), any(ByteBuf.class), any(ChannelPromise.class)); }).when(writer).writeGoAway(eq(ctx), anyInt(), anyInt(), any(ByteBuf.class), any(ChannelPromise.class));
writtenData = new ArrayList<>(); writtenData = new ArrayList<>();
writtenPadding = new ArrayList<>(); writtenPadding = new ArrayList<>();
when(writer.writeData(eq(ctx), anyInt(), any(ByteBuf.class), anyInt(), anyBoolean(), when(writer.writeData(eq(ctx), anyInt(), any(ByteBuf.class), anyInt(), anyBoolean(),
any(ChannelPromise.class))).then(new Answer<ChannelFuture>() { any(ChannelPromise.class))).then((Answer<ChannelFuture>) in -> {
@Override // Make sure we only receive stream closure on the last frame and that void promises
public ChannelFuture answer(InvocationOnMock in) throws Throwable { // are used for all writes except the last one.
// Make sure we only receive stream closure on the last frame and that void promises ChannelPromise promise = (ChannelPromise) in.getArguments()[5];
// are used for all writes except the last one. if (streamClosed) {
ChannelPromise promise = (ChannelPromise) in.getArguments()[5]; fail("Stream already closed");
if (streamClosed) { } else {
fail("Stream already closed"); streamClosed = (Boolean) in.getArguments()[4];
} else {
streamClosed = (Boolean) in.getArguments()[4];
}
writtenPadding.add((Integer) in.getArguments()[3]);
ByteBuf data = (ByteBuf) in.getArguments()[2];
writtenData.add(data.toString(UTF_8));
// Release the buffer just as DefaultHttp2FrameWriter does
data.release();
// Let the promise succeed to trigger listeners.
return promise.setSuccess();
} }
writtenPadding.add((Integer) in.getArguments()[3]);
ByteBuf data = (ByteBuf) in.getArguments()[2];
writtenData.add(data.toString(UTF_8));
// Release the buffer just as DefaultHttp2FrameWriter does
data.release();
// Let the promise succeed to trigger listeners.
return promise.setSuccess();
}); });
when(writer.writeHeaders(eq(ctx), anyInt(), any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(), when(writer.writeHeaders(eq(ctx), anyInt(), any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(),
anyInt(), anyBoolean(), any(ChannelPromise.class))) anyInt(), anyBoolean(), any(ChannelPromise.class)))
.then(new Answer<ChannelFuture>() { .then((Answer<ChannelFuture>) invocationOnMock -> {
@Override ChannelPromise promise = (ChannelPromise) invocationOnMock.getArguments()[8];
public ChannelFuture answer(InvocationOnMock invocationOnMock) throws Throwable { if (streamClosed) {
ChannelPromise promise = (ChannelPromise) invocationOnMock.getArguments()[8]; fail("Stream already closed");
if (streamClosed) { } else {
fail("Stream already closed"); streamClosed = (Boolean) invocationOnMock.getArguments()[5];
} else {
streamClosed = (Boolean) invocationOnMock.getArguments()[5];
}
return promise.setSuccess();
} }
return promise.setSuccess();
}); });
payloadCaptor = ArgumentCaptor.forClass(Http2RemoteFlowController.FlowControlled.class); payloadCaptor = ArgumentCaptor.forClass(Http2RemoteFlowController.FlowControlled.class);
doNothing().when(remoteFlow).addFlowControlled(any(Http2Stream.class), payloadCaptor.capture()); doNothing().when(remoteFlow).addFlowControlled(any(Http2Stream.class), payloadCaptor.capture());
when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT); when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT);
when(ctx.channel()).thenReturn(channel); when(ctx.channel()).thenReturn(channel);
doAnswer(new Answer<ChannelPromise>() { doAnswer((Answer<ChannelPromise>) in -> newPromise()).when(ctx).newPromise();
@Override doAnswer((Answer<ChannelFuture>) in -> newSucceededFuture()).when(ctx).newSucceededFuture();
public ChannelPromise answer(InvocationOnMock in) throws Throwable {
return newPromise();
}
}).when(ctx).newPromise();
doAnswer(new Answer<ChannelFuture>() {
@Override
public ChannelFuture answer(InvocationOnMock in) throws Throwable {
return newSucceededFuture();
}
}).when(ctx).newSucceededFuture();
when(ctx.flush()).thenThrow(new AssertionFailedError("forbidden")); when(ctx.flush()).thenThrow(new AssertionFailedError("forbidden"));
when(channel.alloc()).thenReturn(PooledByteBufAllocator.DEFAULT); when(channel.alloc()).thenReturn(PooledByteBufAllocator.DEFAULT);
@ -337,13 +310,10 @@ public class DefaultHttp2ConnectionEncoderTest {
final Throwable cause = new RuntimeException("fake exception"); final Throwable cause = new RuntimeException("fake exception");
when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(), when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(),
anyInt(), anyBoolean(), any(ChannelPromise.class))) anyInt(), anyBoolean(), any(ChannelPromise.class)))
.then(new Answer<ChannelFuture>() { .then((Answer<ChannelFuture>) invocationOnMock -> {
@Override ChannelPromise promise = invocationOnMock.getArgument(8);
public ChannelFuture answer(InvocationOnMock invocationOnMock) throws Throwable { assertFalse(promise.isVoid());
ChannelPromise promise = invocationOnMock.getArgument(8); return promise.setFailure(cause);
assertFalse(promise.isVoid());
return promise.setFailure(cause);
}
}); });
createStream(STREAM_ID, false); createStream(STREAM_ID, false);
// END_STREAM flag, so that a listener is added to the future. // END_STREAM flag, so that a listener is added to the future.
@ -754,12 +724,9 @@ public class DefaultHttp2ConnectionEncoderTest {
// Fake an encoding error, like HPACK's HeaderListSizeException // Fake an encoding error, like HPACK's HeaderListSizeException
when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), eq(EmptyHttp2Headers.INSTANCE), eq(0), when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), eq(EmptyHttp2Headers.INSTANCE), eq(0),
eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(true), eq(promise))) eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(true), eq(promise)))
.thenAnswer(new Answer<ChannelFuture>() { .thenAnswer((Answer<ChannelFuture>) invocation -> {
@Override promise.setFailure(ex);
public ChannelFuture answer(InvocationOnMock invocation) { return promise;
promise.setFailure(ex);
return promise;
}
}); });
writeAllFlowControlledFrames(); writeAllFlowControlledFrames();
@ -781,12 +748,9 @@ public class DefaultHttp2ConnectionEncoderTest {
// Fake an encoding error, like HPACK's HeaderListSizeException // Fake an encoding error, like HPACK's HeaderListSizeException
when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), eq(EmptyHttp2Headers.INSTANCE), eq(0), when(writer.writeHeaders(eq(ctx), eq(STREAM_ID), eq(EmptyHttp2Headers.INSTANCE), eq(0),
eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(true), eq(promise))) eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(true), eq(promise)))
.thenAnswer(new Answer<ChannelFuture>() { .thenAnswer((Answer<ChannelFuture>) invocation -> {
@Override promise.setFailure(ex);
public ChannelFuture answer(InvocationOnMock invocation) { return promise;
promise.setFailure(ex);
return promise;
}
}); });
writeAllFlowControlledFrames(); writeAllFlowControlledFrames();
@ -873,14 +837,11 @@ public class DefaultHttp2ConnectionEncoderTest {
} }
private void writeAllFlowControlledFrames() { private void writeAllFlowControlledFrames() {
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override FlowControlled flowControlled = (FlowControlled) invocationOnMock.getArguments()[1];
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { flowControlled.write(ctx, Integer.MAX_VALUE);
FlowControlled flowControlled = (FlowControlled) invocationOnMock.getArguments()[1]; flowControlled.writeComplete();
flowControlled.write(ctx, Integer.MAX_VALUE); return null;
flowControlled.writeComplete();
return null;
}
}).when(remoteFlow).addFlowControlled(any(Http2Stream.class), payloadCaptor.capture()); }).when(remoteFlow).addFlowControlled(any(Http2Stream.class), payloadCaptor.capture());
} }

View File

@ -88,19 +88,13 @@ public class DefaultHttp2ConnectionTest {
server = new DefaultHttp2Connection(true); server = new DefaultHttp2Connection(true);
client = new DefaultHttp2Connection(false); client = new DefaultHttp2Connection(false);
client.addListener(clientListener); client.addListener(clientListener);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocation -> {
@Override assertNotNull(client.stream(((Http2Stream) invocation.getArgument(0)).id()));
public Void answer(InvocationOnMock invocation) throws Throwable { return null;
assertNotNull(client.stream(((Http2Stream) invocation.getArgument(0)).id()));
return null;
}
}).when(clientListener).onStreamClosed(any(Http2Stream.class)); }).when(clientListener).onStreamClosed(any(Http2Stream.class));
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocation -> {
@Override assertNull(client.stream(((Http2Stream) invocation.getArgument(0)).id()));
public Void answer(InvocationOnMock invocation) throws Throwable { return null;
assertNull(client.stream(((Http2Stream) invocation.getArgument(0)).id()));
return null;
}
}).when(clientListener).onStreamRemoved(any(Http2Stream.class)); }).when(clientListener).onStreamRemoved(any(Http2Stream.class));
} }
@ -141,13 +135,10 @@ public class DefaultHttp2ConnectionTest {
public void removeIndividualStreamsWhileCloseDoesNotNPE() throws InterruptedException, Http2Exception { public void removeIndividualStreamsWhileCloseDoesNotNPE() throws InterruptedException, Http2Exception {
final Http2Stream streamA = client.local().createStream(3, false); final Http2Stream streamA = client.local().createStream(3, false);
final Http2Stream streamB = client.remote().createStream(2, false); final Http2Stream streamB = client.remote().createStream(2, false);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocation -> {
@Override streamA.close();
public Void answer(InvocationOnMock invocation) throws Throwable { streamB.close();
streamA.close(); return null;
streamB.close();
return null;
}
}).when(clientListener2).onStreamClosed(any(Http2Stream.class)); }).when(clientListener2).onStreamClosed(any(Http2Stream.class));
try { try {
client.addListener(clientListener2); client.addListener(clientListener2);
@ -167,18 +158,12 @@ public class DefaultHttp2ConnectionTest {
} }
final Promise<Void> promise = group.next().newPromise(); final Promise<Void> promise = group.next().newPromise();
final CountDownLatch latch = new CountDownLatch(client.numActiveStreams()); final CountDownLatch latch = new CountDownLatch(client.numActiveStreams());
client.forEachActiveStream(new Http2StreamVisitor() { client.forEachActiveStream(stream -> {
@Override client.close(promise).addListener((FutureListener<Void>) future -> {
public boolean visit(Http2Stream stream) { assertTrue(promise.isDone());
client.close(promise).addListener(new FutureListener<Void>() { latch.countDown();
@Override });
public void operationComplete(Future<Void> future) throws Exception { return true;
assertTrue(promise.isDone());
latch.countDown();
}
});
return true;
}
}); });
assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(latch.await(5, TimeUnit.SECONDS));
} }
@ -195,23 +180,17 @@ public class DefaultHttp2ConnectionTest {
final Promise<Void> promise = group.next().newPromise(); final Promise<Void> promise = group.next().newPromise();
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
try { try {
client.forEachActiveStream(new Http2StreamVisitor() { client.forEachActiveStream(stream -> {
@Override // This close call is basically a noop, because the following statement will throw an exception.
public boolean visit(Http2Stream stream) throws Http2Exception { client.close(promise);
// This close call is basically a noop, because the following statement will throw an exception. // Do an invalid operation while iterating.
client.close(promise); remote.createStream(3, false);
// Do an invalid operation while iterating. return true;
remote.createStream(3, false);
return true;
}
}); });
} catch (Http2Exception ignored) { } catch (Http2Exception ignored) {
client.close(promise).addListener(new FutureListener<Void>() { client.close(promise).addListener((FutureListener<Void>) future -> {
@Override assertTrue(promise.isDone());
public void operationComplete(Future<Void> future) throws Exception { latch.countDown();
assertTrue(promise.isDone());
latch.countDown();
}
}); });
} }
assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(latch.await(5, TimeUnit.SECONDS));
@ -590,12 +569,9 @@ public class DefaultHttp2ConnectionTest {
private void testRemoveAllStreams() throws InterruptedException { private void testRemoveAllStreams() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
final Promise<Void> promise = group.next().newPromise(); final Promise<Void> promise = group.next().newPromise();
client.close(promise).addListener(new FutureListener<Void>() { client.close(promise).addListener((FutureListener<Void>) future -> {
@Override assertTrue(promise.isDone());
public void operationComplete(Future<Void> future) throws Exception { latch.countDown();
assertTrue(promise.isDone());
latch.countDown();
}
}); });
assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(latch.await(5, TimeUnit.SECONDS));
} }

View File

@ -76,16 +76,13 @@ public class DefaultHttp2FrameWriterTest {
http2HeadersEncoder = new DefaultHttp2HeadersEncoder(); http2HeadersEncoder = new DefaultHttp2HeadersEncoder();
Answer<Object> answer = new Answer<Object>() { Answer<Object> answer = var1 -> {
@Override Object msg = var1.getArgument(0);
public Object answer(InvocationOnMock var1) throws Throwable { if (msg instanceof ByteBuf) {
Object msg = var1.getArgument(0); outbound.writeBytes((ByteBuf) msg);
if (msg instanceof ByteBuf) {
outbound.writeBytes((ByteBuf) msg);
}
ReferenceCountUtil.release(msg);
return future;
} }
ReferenceCountUtil.release(msg);
return future;
}; };
when(ctx.write(any())).then(answer); when(ctx.write(any())).then(answer);
when(ctx.write(any(), any(ChannelPromise.class))).then(answer); when(ctx.write(any(), any(ChannelPromise.class))).then(answer);

View File

@ -691,12 +691,9 @@ public abstract class DefaultHttp2RemoteFlowControllerTest {
public void flowControlledWriteThrowsAnException() throws Exception { public void flowControlledWriteThrowsAnException() throws Exception {
final Http2RemoteFlowController.FlowControlled flowControlled = mockedFlowControlledThatThrowsOnWrite(); final Http2RemoteFlowController.FlowControlled flowControlled = mockedFlowControlledThatThrowsOnWrite();
final Http2Stream stream = stream(STREAM_A); final Http2Stream stream = stream(STREAM_A);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override stream.closeLocalSide();
public Void answer(InvocationOnMock invocationOnMock) { return null;
stream.closeLocalSide();
return null;
}
}).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class)); }).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class));
int windowBefore = window(STREAM_A); int windowBefore = window(STREAM_A);
@ -724,11 +721,8 @@ public abstract class DefaultHttp2RemoteFlowControllerTest {
final Http2RemoteFlowController.FlowControlled flowControlled = mockedFlowControlledThatThrowsOnWrite(); final Http2RemoteFlowController.FlowControlled flowControlled = mockedFlowControlledThatThrowsOnWrite();
final Http2Stream stream = stream(STREAM_A); final Http2Stream stream = stream(STREAM_A);
final RuntimeException fakeException = new RuntimeException("error failed"); final RuntimeException fakeException = new RuntimeException("error failed");
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override throw fakeException;
public Void answer(InvocationOnMock invocationOnMock) {
throw fakeException;
}
}).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class)); }).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class));
int windowBefore = window(STREAM_A); int windowBefore = window(STREAM_A);
@ -757,26 +751,15 @@ public abstract class DefaultHttp2RemoteFlowControllerTest {
mock(Http2RemoteFlowController.FlowControlled.class); mock(Http2RemoteFlowController.FlowControlled.class);
Http2Stream streamA = stream(STREAM_A); Http2Stream streamA = stream(STREAM_A);
final AtomicInteger size = new AtomicInteger(150); final AtomicInteger size = new AtomicInteger(150);
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) invocationOnMock -> size.get()).when(flowControlled).size();
@Override doAnswer((Answer<Void>) invocationOnMock -> {
public Integer answer(InvocationOnMock invocationOnMock) throws Throwable { size.addAndGet(-50);
return size.get(); return null;
}
}).when(flowControlled).size();
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
size.addAndGet(-50);
return null;
}
}).when(flowControlled).write(any(ChannelHandlerContext.class), anyInt()); }).when(flowControlled).write(any(ChannelHandlerContext.class), anyInt());
final Http2Stream stream = stream(STREAM_A); final Http2Stream stream = stream(STREAM_A);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override throw new RuntimeException("writeComplete failed");
public Void answer(InvocationOnMock invocationOnMock) {
throw new RuntimeException("writeComplete failed");
}
}).when(flowControlled).writeComplete(); }).when(flowControlled).writeComplete();
int windowBefore = window(STREAM_A); int windowBefore = window(STREAM_A);
@ -807,12 +790,9 @@ public abstract class DefaultHttp2RemoteFlowControllerTest {
when(flowControlled.size()).thenReturn(100); when(flowControlled.size()).thenReturn(100);
doThrow(new RuntimeException("write failed")) doThrow(new RuntimeException("write failed"))
.when(flowControlled).write(any(ChannelHandlerContext.class), anyInt()); .when(flowControlled).write(any(ChannelHandlerContext.class), anyInt());
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override stream.close();
public Void answer(InvocationOnMock invocationOnMock) { return null;
stream.close();
return null;
}
}).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class)); }).when(flowControlled).error(any(ChannelHandlerContext.class), any(Throwable.class));
controller.addFlowControlled(stream, flowControlled); controller.addFlowControlled(stream, flowControlled);
@ -960,13 +940,10 @@ public abstract class DefaultHttp2RemoteFlowControllerTest {
final Http2RemoteFlowController.FlowControlled flowControlled = final Http2RemoteFlowController.FlowControlled flowControlled =
mock(Http2RemoteFlowController.FlowControlled.class); mock(Http2RemoteFlowController.FlowControlled.class);
when(flowControlled.size()).thenReturn(100); when(flowControlled.size()).thenReturn(100);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) in -> {
@Override // Write most of the bytes and then fail
public Void answer(InvocationOnMock in) throws Throwable { when(flowControlled.size()).thenReturn(10);
// Write most of the bytes and then fail throw new RuntimeException("Write failed");
when(flowControlled.size()).thenReturn(10);
throw new RuntimeException("Write failed");
}
}).when(flowControlled).write(any(ChannelHandlerContext.class), anyInt()); }).when(flowControlled).write(any(ChannelHandlerContext.class), anyInt());
return flowControlled; return flowControlled;
} }

View File

@ -51,28 +51,20 @@ public final class HashCollisionTest {
// More "english words" can be found here: // More "english words" can be found here:
// https://gist.github.com/Scottmitch/de2f03912778016ecee3c140478f07e0#file-englishwords-txt // https://gist.github.com/Scottmitch/de2f03912778016ecee3c140478f07e0#file-englishwords-txt
Map<Integer, List<CharSequence>> dups = calculateDuplicates(strings, new Function<CharSequence, Integer>() { Map<Integer, List<CharSequence>> dups = calculateDuplicates(strings, string -> {
@Override int h = 0;
public Integer apply(CharSequence string) { for (int i = 0; i < string.length(); ++i) {
int h = 0; // masking with 0x1F reduces the number of overall bits that impact the hash code but makes the hash
for (int i = 0; i < string.length(); ++i) { // code the same regardless of character case (upper case or lower case hash is the same).
// masking with 0x1F reduces the number of overall bits that impact the hash code but makes the hash h = h * 31 + (string.charAt(i) & 0x1F);
// code the same regardless of character case (upper case or lower case hash is the same).
h = h * 31 + (string.charAt(i) & 0x1F);
}
return h;
} }
return h;
}); });
PrintStream writer = System.out; PrintStream writer = System.out;
writer.println("==Old Duplicates=="); writer.println("==Old Duplicates==");
printResults(writer, dups); printResults(writer, dups);
dups = calculateDuplicates(strings, new Function<CharSequence, Integer>() { dups = calculateDuplicates(strings, PlatformDependent::hashCodeAscii);
@Override
public Integer apply(CharSequence string) {
return PlatformDependent.hashCodeAscii(string);
}
});
writer.println(); writer.println();
writer.println("==New Duplicates=="); writer.println("==New Duplicates==");
printResults(writer, dups); printResults(writer, dups);

View File

@ -180,12 +180,7 @@ final class HpackTestCase {
private static byte[] encode(HpackEncoder hpackEncoder, List<HpackHeaderField> headers, int maxHeaderTableSize, private static byte[] encode(HpackEncoder hpackEncoder, List<HpackHeaderField> headers, int maxHeaderTableSize,
final boolean sensitive) throws Http2Exception { final boolean sensitive) throws Http2Exception {
Http2Headers http2Headers = toHttp2Headers(headers); Http2Headers http2Headers = toHttp2Headers(headers);
Http2HeadersEncoder.SensitivityDetector sensitivityDetector = new Http2HeadersEncoder.SensitivityDetector() { Http2HeadersEncoder.SensitivityDetector sensitivityDetector = (name, value) -> sensitive;
@Override
public boolean isSensitive(CharSequence name, CharSequence value) {
return sensitive;
}
};
ByteBuf buffer = Unpooled.buffer(); ByteBuf buffer = Unpooled.buffer();
try { try {
if (maxHeaderTableSize != -1) { if (maxHeaderTableSize != -1) {

View File

@ -154,25 +154,19 @@ public class Http2ConnectionHandlerTest {
when(encoder.frameWriter()).thenReturn(frameWriter); when(encoder.frameWriter()).thenReturn(frameWriter);
when(encoder.flowController()).thenReturn(remoteFlow); when(encoder.flowController()).thenReturn(remoteFlow);
when(decoder.flowController()).thenReturn(localFlow); when(decoder.flowController()).thenReturn(localFlow);
doAnswer(new Answer<ChannelFuture>() { doAnswer((Answer<ChannelFuture>) invocation -> {
@Override ByteBuf buf = invocation.getArgument(3);
public ChannelFuture answer(InvocationOnMock invocation) throws Throwable { goAwayDebugCap = buf.toString(UTF_8);
ByteBuf buf = invocation.getArgument(3); buf.release();
goAwayDebugCap = buf.toString(UTF_8); return future;
buf.release();
return future;
}
}).when(frameWriter).writeGoAway( }).when(frameWriter).writeGoAway(
any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class)); any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class));
doAnswer(new Answer<ChannelFuture>() { doAnswer((Answer<ChannelFuture>) invocation -> {
@Override Object o = invocation.getArguments()[0];
public ChannelFuture answer(InvocationOnMock invocation) throws Throwable { if (o instanceof ChannelFutureListener) {
Object o = invocation.getArguments()[0]; ((ChannelFutureListener) o).operationComplete(future);
if (o instanceof ChannelFutureListener) {
((ChannelFutureListener) o).operationComplete(future);
}
return future;
} }
return future;
}).when(future).addListener(any(GenericFutureListener.class)); }).when(future).addListener(any(GenericFutureListener.class));
when(future.cause()).thenReturn(fakeException); when(future.cause()).thenReturn(fakeException);
when(future.channel()).thenReturn(channel); when(future.channel()).thenReturn(channel);
@ -182,15 +176,12 @@ public class Http2ConnectionHandlerTest {
when(remote.flowController()).thenReturn(remoteFlowController); when(remote.flowController()).thenReturn(remoteFlowController);
when(connection.local()).thenReturn(local); when(connection.local()).thenReturn(local);
when(local.flowController()).thenReturn(localFlowController); when(local.flowController()).thenReturn(localFlowController);
doAnswer(new Answer<Http2Stream>() { doAnswer((Answer<Http2Stream>) in -> {
@Override Http2StreamVisitor visitor = in.getArgument(0);
public Http2Stream answer(InvocationOnMock in) throws Throwable { if (!visitor.visit(stream)) {
Http2StreamVisitor visitor = in.getArgument(0); return stream;
if (!visitor.visit(stream)) {
return stream;
}
return null;
} }
return null;
}).when(connection).forEachActiveStream(any(Http2StreamVisitor.class)); }).when(connection).forEachActiveStream(any(Http2StreamVisitor.class));
when(connection.stream(NON_EXISTANT_STREAM_ID)).thenReturn(null); when(connection.stream(NON_EXISTANT_STREAM_ID)).thenReturn(null);
when(connection.numActiveStreams()).thenReturn(1); when(connection.numActiveStreams()).thenReturn(1);
@ -205,13 +196,10 @@ public class Http2ConnectionHandlerTest {
when(ctx.voidPromise()).thenReturn(voidPromise); when(ctx.voidPromise()).thenReturn(voidPromise);
when(ctx.write(any())).thenReturn(future); when(ctx.write(any())).thenReturn(future);
when(ctx.executor()).thenReturn(executor); when(ctx.executor()).thenReturn(executor);
doAnswer(new Answer() { doAnswer(in -> {
@Override Object msg = in.getArgument(0);
public Object answer(InvocationOnMock in) throws Throwable { ReferenceCountUtil.release(msg);
Object msg = in.getArgument(0); return null;
ReferenceCountUtil.release(msg);
return null;
}
}).when(ctx).fireChannelRead(any()); }).when(ctx).fireChannelRead(any());
} }
@ -261,15 +249,12 @@ public class Http2ConnectionHandlerTest {
Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.INSTANCE; Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.INSTANCE;
final AtomicBoolean verified = new AtomicBoolean(false); final AtomicBoolean verified = new AtomicBoolean(false);
final Answer verifier = new Answer() { final Answer verifier = in -> {
@Override assertTrue(in.getArgument(0).equals(evt)); // sanity check...
public Object answer(final InvocationOnMock in) throws Throwable { verify(ctx).write(eq(connectionPrefaceBuf()));
assertTrue(in.getArgument(0).equals(evt)); // sanity check... verify(encoder).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class));
verify(ctx).write(eq(connectionPrefaceBuf())); verified.set(true);
verify(encoder).writeSettings(eq(ctx), any(Http2Settings.class), any(ChannelPromise.class)); return null;
verified.set(true);
return null;
}
}; };
doAnswer(verifier).when(ctx).fireUserEventTriggered(evt); doAnswer(verifier).when(ctx).fireUserEventTriggered(evt);
@ -562,23 +547,16 @@ public class Http2ConnectionHandlerTest {
handler = newHandler(); handler = newHandler();
when(future.isDone()).thenReturn(true); when(future.isDone()).thenReturn(true);
when(future.isSuccess()).thenReturn(true); when(future.isSuccess()).thenReturn(true);
doAnswer(new Answer<ChannelFuture>() { doAnswer((Answer<ChannelFuture>) invocation -> {
@Override Object[] args = invocation.getArguments();
public ChannelFuture answer(InvocationOnMock invocation) throws Throwable { GenericFutureListener<ChannelFuture> listener = (GenericFutureListener<ChannelFuture>) args[0];
Object[] args = invocation.getArguments(); // Simulate that all streams have become inactive by the time the future completes.
GenericFutureListener<ChannelFuture> listener = (GenericFutureListener<ChannelFuture>) args[0]; doAnswer((Answer<Http2Stream>) in -> null).when(connection).forEachActiveStream(
// Simulate that all streams have become inactive by the time the future completes. any(Http2StreamVisitor.class));
doAnswer(new Answer<Http2Stream>() { when(connection.numActiveStreams()).thenReturn(0);
@Override // Simulate the future being completed.
public Http2Stream answer(InvocationOnMock in) throws Throwable { listener.operationComplete(future);
return null; return future;
}
}).when(connection).forEachActiveStream(any(Http2StreamVisitor.class));
when(connection.numActiveStreams()).thenReturn(0);
// Simulate the future being completed.
listener.operationComplete(future);
return future;
}
}).when(future).addListener(any(GenericFutureListener.class)); }).when(future).addListener(any(GenericFutureListener.class));
handler.close(ctx, promise); handler.close(ctx, promise);
if (future.isDone()) { if (future.isDone()) {
@ -597,12 +575,9 @@ public class Http2ConnectionHandlerTest {
long errorCode = Http2Error.INTERNAL_ERROR.code(); long errorCode = Http2Error.INTERNAL_ERROR.code();
when(future.isDone()).thenReturn(true); when(future.isDone()).thenReturn(true);
when(future.isSuccess()).thenReturn(true); when(future.isSuccess()).thenReturn(true);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocation -> {
@Override ((GenericFutureListener) invocation.getArgument(0)).operationComplete(future);
public Void answer(InvocationOnMock invocation) throws Throwable { return null;
((GenericFutureListener) invocation.getArgument(0)).operationComplete(future);
return null;
}
}).when(future).addListener(any(GenericFutureListener.class)); }).when(future).addListener(any(GenericFutureListener.class));
handler = newHandler(); handler = newHandler();
handler.goAway(ctx, STREAM_ID, errorCode, data, promise); handler.goAway(ctx, STREAM_ID, errorCode, data, promise);
@ -645,11 +620,8 @@ public class Http2ConnectionHandlerTest {
when(connection.goAwaySent()).thenReturn(true); when(connection.goAwaySent()).thenReturn(true);
when(remote.lastStreamKnownByPeer()).thenReturn(STREAM_ID); when(remote.lastStreamKnownByPeer()).thenReturn(STREAM_ID);
doAnswer(new Answer<Boolean>() { doAnswer((Answer<Boolean>) invocationOnMock -> {
@Override throw new IllegalStateException();
public Boolean answer(InvocationOnMock invocationOnMock) {
throw new IllegalStateException();
}
}).when(connection).goAwaySent(anyInt(), anyLong(), any(ByteBuf.class)); }).when(connection).goAwaySent(anyInt(), anyLong(), any(ByteBuf.class));
handler.goAway(ctx, STREAM_ID + 2, errorCode, data, promise); handler.goAway(ctx, STREAM_ID + 2, errorCode, data, promise);
assertTrue(promise.isDone()); assertTrue(promise.isDone());
@ -665,18 +637,15 @@ public class Http2ConnectionHandlerTest {
long errorCode = Http2Error.INTERNAL_ERROR.code(); long errorCode = Http2Error.INTERNAL_ERROR.code();
handler = newHandler(); handler = newHandler();
final Throwable cause = new RuntimeException("fake exception"); final Throwable cause = new RuntimeException("fake exception");
doAnswer(new Answer<ChannelFuture>() { doAnswer((Answer<ChannelFuture>) invocation -> {
@Override ChannelPromise promise = invocation.getArgument(4);
public ChannelFuture answer(InvocationOnMock invocation) throws Throwable { assertFalse(promise.isVoid());
ChannelPromise promise = invocation.getArgument(4); // This is what DefaultHttp2FrameWriter does... I hate mocking :-(.
assertFalse(promise.isVoid()); SimpleChannelPromiseAggregator aggregatedPromise =
// This is what DefaultHttp2FrameWriter does... I hate mocking :-(. new SimpleChannelPromiseAggregator(promise, channel, ImmediateEventExecutor.INSTANCE);
SimpleChannelPromiseAggregator aggregatedPromise = aggregatedPromise.newPromise();
new SimpleChannelPromiseAggregator(promise, channel, ImmediateEventExecutor.INSTANCE); aggregatedPromise.doneAllocatingPromises();
aggregatedPromise.newPromise(); return aggregatedPromise.setFailure(cause);
aggregatedPromise.doneAllocatingPromises();
return aggregatedPromise.setFailure(cause);
}
}).when(frameWriter).writeGoAway( }).when(frameWriter).writeGoAway(
any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class)); any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class));
handler.goAway(ctx, STREAM_ID, errorCode, data, newVoidPromise(channel)); handler.goAway(ctx, STREAM_ID, errorCode, data, newVoidPromise(channel));
@ -742,13 +711,10 @@ public class Http2ConnectionHandlerTest {
final Throwable cause = new RuntimeException("fake exception"); final Throwable cause = new RuntimeException("fake exception");
when(stream.id()).thenReturn(STREAM_ID); when(stream.id()).thenReturn(STREAM_ID);
when(frameWriter.writeRstStream(eq(ctx), eq(streamId), anyLong(), any(ChannelPromise.class))) when(frameWriter.writeRstStream(eq(ctx), eq(streamId), anyLong(), any(ChannelPromise.class)))
.then(new Answer<ChannelFuture>() { .then((Answer<ChannelFuture>) invocationOnMock -> {
@Override ChannelPromise promise = invocationOnMock.getArgument(3);
public ChannelFuture answer(InvocationOnMock invocationOnMock) throws Throwable { assertFalse(promise.isVoid());
ChannelPromise promise = invocationOnMock.getArgument(3); return promise.setFailure(cause);
assertFalse(promise.isVoid());
return promise.setFailure(cause);
}
}); });
handler.resetStream(ctx, streamId, STREAM_CLOSED.code(), newVoidPromise(channel)); handler.resetStream(ctx, streamId, STREAM_CLOSED.code(), newVoidPromise(channel));
verify(frameWriter).writeRstStream(eq(ctx), eq(streamId), anyLong(), any(ChannelPromise.class)); verify(frameWriter).writeRstStream(eq(ctx), eq(streamId), anyLong(), any(ChannelPromise.class));

View File

@ -148,50 +148,38 @@ public class Http2ConnectionRoundtripTest {
public void inflightFrameAfterStreamResetShouldNotMakeConnectionUnusable() throws Exception { public void inflightFrameAfterStreamResetShouldNotMakeConnectionUnusable() throws Exception {
bootstrapEnv(1, 1, 2, 1); bootstrapEnv(1, 1, 2, 1);
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
doAnswer(new Answer<Void>() { doAnswer(invocationOnMock -> {
@Override ChannelHandlerContext ctx = invocationOnMock.getArgument(0);
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { http2Server.encoder().writeHeaders(ctx,
ChannelHandlerContext ctx = invocationOnMock.getArgument(0); (Integer) invocationOnMock.getArgument(1),
http2Server.encoder().writeHeaders(ctx, (Http2Headers) invocationOnMock.getArgument(2),
(Integer) invocationOnMock.getArgument(1), 0,
(Http2Headers) invocationOnMock.getArgument(2), false,
0, ctx.newPromise());
false, http2Server.flush(ctx);
ctx.newPromise()); return null;
http2Server.flush(ctx);
return null;
}
}).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class), }).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class),
anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean()); anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean());
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override latch.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { return null;
latch.countDown();
return null;
}
}).when(clientListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), any(Http2Headers.class), }).when(clientListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), any(Http2Headers.class),
anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean()); anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean());
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final short weight = 16; final short weight = 16;
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, weight, false, 0, false, newPromise());
public void run() throws Http2Exception { http2Client.flush(ctx());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, weight, false, 0, false, newPromise()); http2Client.encoder().writeRstStream(ctx(), 3, Http2Error.INTERNAL_ERROR.code(), newPromise());
http2Client.flush(ctx()); http2Client.flush(ctx());
http2Client.encoder().writeRstStream(ctx(), 3, Http2Error.INTERNAL_ERROR.code(), newPromise());
http2Client.flush(ctx());
}
}); });
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, weight, false, 0, false, newPromise());
public void run() throws Http2Exception { http2Client.flush(ctx());
http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, weight, false, 0, false, newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(latch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(latch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -204,13 +192,10 @@ public class Http2ConnectionRoundtripTest {
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final short weight = 16; final short weight = 16;
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, weight, false, 0, true,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, weight, false, 0, true, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -245,68 +230,45 @@ public class Http2ConnectionRoundtripTest {
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override serverSettingsAckLatch1.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { serverSettingsAckLatch2.countDown();
serverSettingsAckLatch1.countDown(); return null;
serverSettingsAckLatch2.countDown();
return null;
}
}).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class)); }).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class));
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override clientSettingsLatch1.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { return null;
clientSettingsLatch1.countDown();
return null;
}
}).when(clientListener).onSettingsRead(any(ChannelHandlerContext.class), any(Http2Settings.class)); }).when(clientListener).onSettingsRead(any(ChannelHandlerContext.class), any(Http2Settings.class));
// Manually add a listener for when we receive the expected headers on the server. // Manually add a listener for when we receive the expected headers on the server.
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override serverRevHeadersLatch.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { return null;
serverRevHeadersLatch.countDown();
return null;
}
}).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), eq(headers), }).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), eq(headers),
anyInt(), anyShort(), anyBoolean(), eq(0), eq(true)); anyInt(), anyShort(), anyBoolean(), eq(0), eq(true));
// Set the maxHeaderListSize to 100 so we may be able to write some headers, but not all. We want to verify // Set the maxHeaderListSize to 100 so we may be able to write some headers, but not all. We want to verify
// that we don't corrupt state if some can be written but not all. // that we don't corrupt state if some can be written but not all.
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override http2Server.encoder().writeSettings(serverCtx(),
public void run() throws Http2Exception { new Http2Settings().copyFrom(http2Server.decoder().localSettings())
http2Server.encoder().writeSettings(serverCtx(), .maxHeaderListSize(100),
new Http2Settings().copyFrom(http2Server.decoder().localSettings()) serverNewPromise());
.maxHeaderListSize(100), http2Server.flush(serverCtx());
serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, false, newPromise())
public void run() throws Http2Exception { .addListener((ChannelFutureListener) future -> clientHeadersWriteException.set(future.cause()));
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, false, newPromise()) // It is expected that this write should fail locally and the remote peer will never see this.
.addListener(new ChannelFutureListener() { http2Client.encoder().writeData(ctx(), 3, Unpooled.buffer(), 0, true, newPromise())
@Override .addListener((ChannelFutureListener) future -> {
public void operationComplete(ChannelFuture future) throws Exception { clientDataWriteException.set(future.cause());
clientHeadersWriteException.set(future.cause()); clientDataWrite.countDown();
}
}); });
// It is expected that this write should fail locally and the remote peer will never see this. http2Client.flush(ctx());
http2Client.encoder().writeData(ctx(), 3, Unpooled.buffer(), 0, true, newPromise())
.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientDataWriteException.set(future.cause());
clientDataWrite.countDown();
}
});
http2Client.flush(ctx());
}
}); });
assertTrue(clientDataWrite.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(clientDataWrite.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -314,33 +276,24 @@ public class Http2ConnectionRoundtripTest {
assertNotNull("Data on closed stream should fail!", clientDataWriteException.get()); assertNotNull("Data on closed stream should fail!", clientDataWriteException.get());
// Set the maxHeaderListSize to the max value so we can send the headers. // Set the maxHeaderListSize to the max value so we can send the headers.
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override http2Server.encoder().writeSettings(serverCtx(),
public void run() throws Http2Exception { new Http2Settings().copyFrom(http2Server.decoder().localSettings())
http2Server.encoder().writeSettings(serverCtx(), .maxHeaderListSize(Http2CodecUtil.MAX_HEADER_LIST_SIZE),
new Http2Settings().copyFrom(http2Server.decoder().localSettings()) serverNewPromise());
.maxHeaderListSize(Http2CodecUtil.MAX_HEADER_LIST_SIZE), http2Server.flush(serverCtx());
serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
assertTrue(clientSettingsLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(clientSettingsLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, true,
public void run() throws Http2Exception { newPromise()).addListener((ChannelFutureListener) future -> {
http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, true, clientHeadersWriteException2.set(future.cause());
newPromise()).addListener(new ChannelFutureListener() { clientHeadersLatch.countDown();
@Override });
public void operationComplete(ChannelFuture future) throws Exception { http2Client.flush(ctx());
clientHeadersWriteException2.set(future.cause());
clientHeadersLatch.countDown();
}
});
http2Client.flush(ctx());
}
}); });
assertTrue(clientHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(clientHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -371,69 +324,54 @@ public class Http2ConnectionRoundtripTest {
final byte[] data = new byte[] {1, 2, 3, 4, 5}; final byte[] data = new byte[] {1, 2, 3, 4, 5};
final ByteArrayOutputStream out = new ByteArrayOutputStream(data.length); final ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override serverSettingsAckLatch1.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { serverSettingsAckLatch2.countDown();
serverSettingsAckLatch1.countDown(); return null;
serverSettingsAckLatch2.countDown();
return null;
}
}).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class)); }).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class));
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) in -> {
@Override ByteBuf buf = (ByteBuf) in.getArguments()[2];
public Integer answer(InvocationOnMock in) throws Throwable { int padding = (Integer) in.getArguments()[3];
ByteBuf buf = (ByteBuf) in.getArguments()[2]; int processedBytes = buf.readableBytes() + padding;
int padding = (Integer) in.getArguments()[3];
int processedBytes = buf.readableBytes() + padding;
buf.readBytes(out, buf.readableBytes()); buf.readBytes(out, buf.readableBytes());
serverDataLatch.countDown(); serverDataLatch.countDown();
return processedBytes; return processedBytes;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3),
any(ByteBuf.class), eq(0), anyBoolean()); any(ByteBuf.class), eq(0), anyBoolean());
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
// The server initially reduces the connection flow control window to 0. // The server initially reduces the connection flow control window to 0.
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override http2Server.encoder().writeSettings(serverCtx(),
public void run() throws Http2Exception { new Http2Settings().copyFrom(http2Server.decoder().localSettings())
http2Server.encoder().writeSettings(serverCtx(), .initialWindowSize(0),
new Http2Settings().copyFrom(http2Server.decoder().localSettings()) serverNewPromise());
.initialWindowSize(0), http2Server.flush(serverCtx());
serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
// The client should now attempt to send data, but the window size is 0 so it will be queued in the flow // The client should now attempt to send data, but the window size is 0 so it will be queued in the flow
// controller. // controller.
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.encoder().writeData(ctx(), 3, Unpooled.wrappedBuffer(data), 0, true, newPromise());
newPromise()); http2Client.flush(ctx());
http2Client.encoder().writeData(ctx(), 3, Unpooled.wrappedBuffer(data), 0, true, newPromise()); clientWriteDataLatch.countDown();
http2Client.flush(ctx());
clientWriteDataLatch.countDown();
}
}); });
assertTrue(clientWriteDataLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(clientWriteDataLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
// Now the server opens up the connection window to allow the client to send the pending data. // Now the server opens up the connection window to allow the client to send the pending data.
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override http2Server.encoder().writeSettings(serverCtx(),
public void run() throws Http2Exception { new Http2Settings().copyFrom(http2Server.decoder().localSettings())
http2Server.encoder().writeSettings(serverCtx(), .initialWindowSize(data.length),
new Http2Settings().copyFrom(http2Server.decoder().localSettings()) serverNewPromise());
.initialWindowSize(data.length), http2Server.flush(serverCtx());
serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -454,14 +392,11 @@ public class Http2ConnectionRoundtripTest {
bootstrapEnv(1, 1, 2, 0); bootstrapEnv(1, 1, 2, 0);
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writePriority(ctx(), 5, 3, (short) 14, false, newPromise());
public void run() throws Http2Exception { http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
http2Client.encoder().writePriority(ctx(), 5, 3, (short) 14, false, newPromise()); newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -486,15 +421,12 @@ public class Http2ConnectionRoundtripTest {
bootstrapEnv(1, 1, 1, 0); bootstrapEnv(1, 1, 1, 0);
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0, false, http2Client.encoder().frameWriter().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
newPromise()); newPromise());
http2Client.encoder().frameWriter().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -525,24 +457,18 @@ public class Http2ConnectionRoundtripTest {
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
final int streamId = 3; final int streamId = 3;
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), streamId, headers, CONNECTION_STREAM_ID,
public void run() throws Http2Exception { DEFAULT_PRIORITY_WEIGHT, false, 0, false, newPromise());
http2Client.encoder().writeHeaders(ctx(), streamId, headers, CONNECTION_STREAM_ID, http2Client.encoder().writeRstStream(ctx(), streamId, Http2Error.CANCEL.code(), newPromise());
DEFAULT_PRIORITY_WEIGHT, false, 0, false, newPromise()); http2Client.flush(ctx());
http2Client.encoder().writeRstStream(ctx(), streamId, Http2Error.CANCEL.code(), newPromise());
http2Client.flush(ctx());
}
}); });
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override if (streamId == (Integer) invocationOnMock.getArgument(1)) {
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { serverGotRstLatch.countDown();
if (streamId == (Integer) invocationOnMock.getArgument(1)) {
serverGotRstLatch.countDown();
}
return null;
} }
return null;
}).when(serverListener).onRstStreamRead(any(ChannelHandlerContext.class), eq(streamId), anyLong()); }).when(serverListener).onRstStreamRead(any(ChannelHandlerContext.class), eq(streamId), anyLong());
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -552,19 +478,13 @@ public class Http2ConnectionRoundtripTest {
anyShort(), anyBoolean(), anyInt(), eq(false)); anyShort(), anyBoolean(), anyInt(), eq(false));
// Now have the server attempt to send a headers frame simulating some asynchronous work. // Now have the server attempt to send a headers frame simulating some asynchronous work.
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override http2Server.encoder().writeHeaders(serverCtx(), streamId, headers, 0, true, serverNewPromise())
public void run() throws Http2Exception { .addListener((ChannelFutureListener) future -> {
http2Server.encoder().writeHeaders(serverCtx(), streamId, headers, 0, true, serverNewPromise()) serverWriteHeadersCauseRef.set(future.cause());
.addListener(new ChannelFutureListener() { serverWriteHeadersLatch.countDown();
@Override });
public void operationComplete(ChannelFuture future) throws Exception { http2Server.flush(serverCtx());
serverWriteHeadersCauseRef.set(future.cause());
serverWriteHeadersLatch.countDown();
}
});
http2Server.flush(serverCtx());
}
}); });
assertTrue(serverWriteHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverWriteHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -586,22 +506,14 @@ public class Http2ConnectionRoundtripTest {
// Create a latch to track when the close occurs. // Create a latch to track when the close occurs.
final CountDownLatch closeLatch = new CountDownLatch(1); final CountDownLatch closeLatch = new CountDownLatch(1);
clientChannel.closeFuture().addListener(new ChannelFutureListener() { clientChannel.closeFuture().addListener((ChannelFutureListener) future -> closeLatch.countDown());
@Override
public void operationComplete(ChannelFuture future) throws Exception {
closeLatch.countDown();
}
});
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
// Wait for the server to create the stream. // Wait for the server to create the stream.
@ -632,21 +544,13 @@ public class Http2ConnectionRoundtripTest {
// Create a latch to track when the close occurs. // Create a latch to track when the close occurs.
final CountDownLatch closeLatch = new CountDownLatch(1); final CountDownLatch closeLatch = new CountDownLatch(1);
clientChannel.closeFuture().addListener(new ChannelFutureListener() { clientChannel.closeFuture().addListener((ChannelFutureListener) future -> closeLatch.countDown());
@Override
public void operationComplete(ChannelFuture future) throws Exception {
closeLatch.countDown();
}
});
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
// Wait for the server to create the stream. // Wait for the server to create the stream.
@ -690,37 +594,34 @@ public class Http2ConnectionRoundtripTest {
bootstrapEnv(1, 1, 2, 1); bootstrapEnv(1, 1, 2, 1);
final ChannelPromise emptyDataPromise = newPromise(); final ChannelPromise emptyDataPromise = newPromise();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, false, ByteBuf emptyBuf = Unpooled.buffer();
newPromise()); emptyBuf.release();
ByteBuf emptyBuf = Unpooled.buffer(); switch (mode) {
emptyBuf.release(); case SINGLE_END_OF_STREAM:
switch (mode) { http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, true, emptyDataPromise);
case SINGLE_END_OF_STREAM: break;
http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, true, emptyDataPromise); case SECOND_END_OF_STREAM:
break; http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
case SECOND_END_OF_STREAM: http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, true, newPromise());
http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise); break;
http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, true, newPromise()); case SINGLE_WITH_TRAILERS:
break; http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
case SINGLE_WITH_TRAILERS: http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0,
http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise); (short) 16, false, 0, true, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, break;
(short) 16, false, 0, true, newPromise()); case SECOND_WITH_TRAILERS:
break; http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
case SECOND_WITH_TRAILERS: http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, false, newPromise());
http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise); http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0,
http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, false, newPromise()); (short) 16, false, 0, true, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, break;
(short) 16, false, 0, true, newPromise()); default:
break; throw new Error();
default:
throw new Error();
}
http2Client.flush(ctx());
} }
http2Client.flush(ctx());
}); });
try { try {
@ -739,38 +640,35 @@ public class Http2ConnectionRoundtripTest {
final ChannelPromise dataPromise = newPromise(); final ChannelPromise dataPromise = newPromise();
final ChannelPromise assertPromise = newPromise(); final ChannelPromise assertPromise = newPromise();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, false, clientChannel.pipeline().addFirst(new ChannelOutboundHandlerAdapter() {
newPromise()); @Override
clientChannel.pipeline().addFirst(new ChannelOutboundHandlerAdapter() { public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
@Override ReferenceCountUtil.release(msg);
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ReferenceCountUtil.release(msg);
// Ensure we update the window size so we will try to write the rest of the frame while // Ensure we update the window size so we will try to write the rest of the frame while
// processing the flush. // processing the flush.
http2Client.encoder().flowController().initialWindowSize(8); http2Client.encoder().flowController().initialWindowSize(8);
promise.setFailure(new IllegalStateException()); promise.setFailure(new IllegalStateException());
}
});
http2Client.encoder().flowController().initialWindowSize(4);
http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, false, dataPromise);
assertTrue(http2Client.encoder().flowController()
.hasFlowControlled(http2Client.connection().stream(3)));
http2Client.flush(ctx());
try {
// The Frame should have been removed after the write failed.
assertFalse(http2Client.encoder().flowController()
.hasFlowControlled(http2Client.connection().stream(3)));
assertPromise.setSuccess();
} catch (Throwable error) {
assertPromise.setFailure(error);
} }
});
http2Client.encoder().flowController().initialWindowSize(4);
http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, false, dataPromise);
assertTrue(http2Client.encoder().flowController()
.hasFlowControlled(http2Client.connection().stream(3)));
http2Client.flush(ctx());
try {
// The Frame should have been removed after the write failed.
assertFalse(http2Client.encoder().flowController()
.hasFlowControlled(http2Client.connection().stream(3)));
assertPromise.setSuccess();
} catch (Throwable error) {
assertPromise.setFailure(error);
} }
}); });
@ -790,22 +688,14 @@ public class Http2ConnectionRoundtripTest {
// Create a latch to track when the close occurs. // Create a latch to track when the close occurs.
final CountDownLatch closeLatch = new CountDownLatch(1); final CountDownLatch closeLatch = new CountDownLatch(1);
clientChannel.closeFuture().addListener(new ChannelFutureListener() { clientChannel.closeFuture().addListener((ChannelFutureListener) future -> closeLatch.countDown());
@Override
public void operationComplete(ChannelFuture future) throws Exception {
closeLatch.countDown();
}
});
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false,
public void run() throws Http2Exception { newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, http2Client.flush(ctx());
newPromise());
http2Client.flush(ctx());
}
}); });
// Wait for the server to create the stream. // Wait for the server to create the stream.
@ -837,24 +727,18 @@ public class Http2ConnectionRoundtripTest {
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { true, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, http2Client.flush(ctx());
true, newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), MAX_VALUE + 1, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { true, newPromise());
http2Client.encoder().writeHeaders(ctx(), MAX_VALUE + 1, headers, 0, (short) 16, false, 0, http2Client.flush(ctx());
true, newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(goAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(goAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -871,23 +755,17 @@ public class Http2ConnectionRoundtripTest {
setServerGracefulShutdownTime(10000); setServerGracefulShutdownTime(10000);
final CountDownLatch clientGoAwayLatch = new CountDownLatch(1); final CountDownLatch clientGoAwayLatch = new CountDownLatch(1);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override clientGoAwayLatch.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { return null;
clientGoAwayLatch.countDown();
return null;
}
}).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class)); }).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
// Create a single stream by sending a HEADERS frame to the server. // Create a single stream by sending a HEADERS frame to the server.
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { false, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, http2Client.flush(ctx());
false, newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -895,12 +773,9 @@ public class Http2ConnectionRoundtripTest {
// Server has received the headers, so the stream is open // Server has received the headers, so the stream is open
assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(serverChannel, new Http2Runnable() { runInChannel(serverChannel, () -> {
@Override http2Server.encoder().writeGoAway(serverCtx(), 3, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
public void run() throws Http2Exception { http2Server.flush(serverCtx());
http2Server.encoder().writeGoAway(serverCtx(), 3, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
// wait for the client to receive the GO_AWAY. // wait for the client to receive the GO_AWAY.
@ -910,20 +785,12 @@ public class Http2ConnectionRoundtripTest {
final AtomicReference<ChannelFuture> clientWriteAfterGoAwayFutureRef = new AtomicReference<>(); final AtomicReference<ChannelFuture> clientWriteAfterGoAwayFutureRef = new AtomicReference<>();
final CountDownLatch clientWriteAfterGoAwayLatch = new CountDownLatch(1); final CountDownLatch clientWriteAfterGoAwayLatch = new CountDownLatch(1);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override ChannelFuture f = http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { true, newPromise());
ChannelFuture f = http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0, clientWriteAfterGoAwayFutureRef.set(f);
true, newPromise()); http2Client.flush(ctx());
clientWriteAfterGoAwayFutureRef.set(f); f.addListener((ChannelFutureListener) future -> clientWriteAfterGoAwayLatch.countDown());
http2Client.flush(ctx());
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientWriteAfterGoAwayLatch.countDown();
}
});
}
}); });
// Wait for the client's write operation to complete. // Wait for the client's write operation to complete.
@ -950,12 +817,9 @@ public class Http2ConnectionRoundtripTest {
bootstrapEnv(1, 1, 2, 1, 1); bootstrapEnv(1, 1, 2, 1, 1);
final CountDownLatch clientGoAwayLatch = new CountDownLatch(1); final CountDownLatch clientGoAwayLatch = new CountDownLatch(1);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override clientGoAwayLatch.countDown();
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { return null;
clientGoAwayLatch.countDown();
return null;
}
}).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class)); }).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
// We want both sides to do graceful shutdown during the test. // We want both sides to do graceful shutdown during the test.
@ -965,30 +829,19 @@ public class Http2ConnectionRoundtripTest {
final Http2Headers headers = dummyHeaders(); final Http2Headers headers = dummyHeaders();
final AtomicReference<ChannelFuture> clientWriteAfterGoAwayFutureRef = new AtomicReference<>(); final AtomicReference<ChannelFuture> clientWriteAfterGoAwayFutureRef = new AtomicReference<>();
final CountDownLatch clientWriteAfterGoAwayLatch = new CountDownLatch(1); final CountDownLatch clientWriteAfterGoAwayLatch = new CountDownLatch(1);
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) invocationOnMock -> {
@Override ChannelFuture f = http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0,
public Void answer(InvocationOnMock invocationOnMock) throws Throwable { true, newPromise());
ChannelFuture f = http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0, clientWriteAfterGoAwayFutureRef.set(f);
true, newPromise()); f.addListener((ChannelFutureListener) future -> clientWriteAfterGoAwayLatch.countDown());
clientWriteAfterGoAwayFutureRef.set(f); http2Client.flush(ctx());
f.addListener(new ChannelFutureListener() { return null;
@Override
public void operationComplete(ChannelFuture future) throws Exception {
clientWriteAfterGoAwayLatch.countDown();
}
});
http2Client.flush(ctx());
return null;
}
}).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class)); }).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { true, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, http2Client.flush(ctx());
true, newPromise());
http2Client.flush(ctx());
}
}); });
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
@ -996,12 +849,9 @@ public class Http2ConnectionRoundtripTest {
// Server has received the headers, so the stream is open // Server has received the headers, so the stream is open
assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(serverChannel, new Http2Runnable() { runInChannel(serverChannel, () -> {
@Override http2Server.encoder().writeGoAway(serverCtx(), 3, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
public void run() throws Http2Exception { http2Server.flush(serverCtx());
http2Server.encoder().writeGoAway(serverCtx(), 3, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
http2Server.flush(serverCtx());
}
}); });
// Wait for the client's write operation to complete. // Wait for the client's write operation to complete.
@ -1033,16 +883,13 @@ public class Http2ConnectionRoundtripTest {
// Create a buffer filled with random bytes. // Create a buffer filled with random bytes.
final ByteBuf data = randomBytes(length); final ByteBuf data = randomBytes(length);
final ByteArrayOutputStream out = new ByteArrayOutputStream(length); final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) in -> {
@Override ByteBuf buf = (ByteBuf) in.getArguments()[2];
public Integer answer(InvocationOnMock in) throws Throwable { int padding = (Integer) in.getArguments()[3];
ByteBuf buf = (ByteBuf) in.getArguments()[2]; int processedBytes = buf.readableBytes() + padding;
int padding = (Integer) in.getArguments()[3];
int processedBytes = buf.readableBytes() + padding;
buf.readBytes(out, buf.readableBytes()); buf.readBytes(out, buf.readableBytes());
return processedBytes; return processedBytes;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3),
any(ByteBuf.class), eq(0), anyBoolean()); any(ByteBuf.class), eq(0), anyBoolean());
try { try {
@ -1050,18 +897,15 @@ public class Http2ConnectionRoundtripTest {
bootstrapEnv(length, 1, 2, 1); bootstrapEnv(length, 1, 2, 1);
// Create the stream and send all of the data at once. // Create the stream and send all of the data at once.
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
public void run() throws Http2Exception { false, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, http2Client.encoder().writeData(ctx(), 3, data.retainedDuplicate(), 0, false, newPromise());
false, newPromise());
http2Client.encoder().writeData(ctx(), 3, data.retainedDuplicate(), 0, false, newPromise());
// Write trailers. // Write trailers.
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0,
true, newPromise()); true, newPromise());
http2Client.flush(ctx()); http2Client.flush(ctx());
}
}); });
// Wait for the trailers to be received. // Wait for the trailers to be received.
@ -1110,44 +954,38 @@ public class Http2ConnectionRoundtripTest {
// Collect all the data buffers as we receive them at the server. // Collect all the data buffers as we receive them at the server.
final StringBuilder[] receivedData = new StringBuilder[numStreams]; final StringBuilder[] receivedData = new StringBuilder[numStreams];
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) in -> {
@Override int streamId = (Integer) in.getArguments()[1];
public Integer answer(InvocationOnMock in) throws Throwable { ByteBuf buf = (ByteBuf) in.getArguments()[2];
int streamId = (Integer) in.getArguments()[1]; int padding = (Integer) in.getArguments()[3];
ByteBuf buf = (ByteBuf) in.getArguments()[2]; int processedBytes = buf.readableBytes() + padding;
int padding = (Integer) in.getArguments()[3];
int processedBytes = buf.readableBytes() + padding;
int streamIndex = (streamId - 3) / 2; int streamIndex = (streamId - 3) / 2;
StringBuilder builder = receivedData[streamIndex]; StringBuilder builder = receivedData[streamIndex];
if (builder == null) { if (builder == null) {
builder = new StringBuilder(dataAsHex.length()); builder = new StringBuilder(dataAsHex.length());
receivedData[streamIndex] = builder; receivedData[streamIndex] = builder;
}
builder.append(ByteBufUtil.hexDump(buf));
return processedBytes;
} }
builder.append(ByteBufUtil.hexDump(buf));
return processedBytes;
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), anyInt(), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), anyInt(),
any(ByteBuf.class), anyInt(), anyBoolean()); any(ByteBuf.class), anyInt(), anyBoolean());
try { try {
bootstrapEnv(numStreams * length, 1, numStreams * 4, numStreams); bootstrapEnv(numStreams * length, 1, numStreams * 4, numStreams);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override int upperLimit = 3 + 2 * numStreams;
public void run() throws Http2Exception { for (int streamId = 3; streamId < upperLimit; streamId += 2) {
int upperLimit = 3 + 2 * numStreams; // Send a bunch of data on each stream.
for (int streamId = 3; streamId < upperLimit; streamId += 2) { http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
// Send a bunch of data on each stream. false, 0, false, newPromise());
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16, http2Client.encoder().writePing(ctx(), false, pingData,
false, 0, false, newPromise()); newPromise());
http2Client.encoder().writePing(ctx(), false, pingData, http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0,
newPromise()); false, newPromise());
http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0, // Write trailers.
false, newPromise()); http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16,
// Write trailers. false, 0, true, newPromise());
http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16, http2Client.flush(ctx());
false, 0, true, newPromise());
http2Client.flush(ctx());
}
} }
}); });
// Wait for all frames to be received. // Wait for all frames to be received.
@ -1270,15 +1108,11 @@ public class Http2ConnectionRoundtripTest {
} }
private static void mockFlowControl(Http2FrameListener listener) throws Http2Exception { private static void mockFlowControl(Http2FrameListener listener) throws Http2Exception {
doAnswer(new Answer<Integer>() { doAnswer((Answer<Integer>) invocation -> {
@Override ByteBuf buf = (ByteBuf) invocation.getArguments()[2];
public Integer answer(InvocationOnMock invocation) throws Throwable { int padding = (Integer) invocation.getArguments()[3];
ByteBuf buf = (ByteBuf) invocation.getArguments()[2]; int processedBytes = buf.readableBytes() + padding;
int padding = (Integer) invocation.getArguments()[3]; return processedBytes;
int processedBytes = buf.readableBytes() + padding;
return processedBytes;
}
}).when(listener).onDataRead(any(ChannelHandlerContext.class), anyInt(), }).when(listener).onDataRead(any(ChannelHandlerContext.class), anyInt(),
any(ByteBuf.class), anyInt(), anyBoolean()); any(ByteBuf.class), anyInt(), anyBoolean());
} }
@ -1294,12 +1128,9 @@ public class Http2ConnectionRoundtripTest {
private static void setGracefulShutdownTime(Channel channel, final Http2ConnectionHandler handler, private static void setGracefulShutdownTime(Channel channel, final Http2ConnectionHandler handler,
final long millis) throws InterruptedException { final long millis) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
runInChannel(channel, new Http2Runnable() { runInChannel(channel, () -> {
@Override handler.gracefulShutdownTimeoutMillis(millis);
public void run() throws Http2Exception { latch.countDown();
handler.gracefulShutdownTimeoutMillis(millis);
latch.countDown();
}
}); });
assertTrue(latch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS)); assertTrue(latch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));

View File

@ -573,15 +573,12 @@ public class Http2FrameCodecTest {
final Promise<Void> listenerExecuted = new DefaultPromise<>(GlobalEventExecutor.INSTANCE); final Promise<Void> listenerExecuted = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
channel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers(), false).stream(stream)) channel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers(), false).stream(stream))
.addListener(new ChannelFutureListener() { .addListener((ChannelFutureListener) future -> {
@Override assertTrue(future.isSuccess());
public void operationComplete(ChannelFuture future) throws Exception { assertTrue(isStreamIdValid(stream.id()));
assertTrue(future.isSuccess()); listenerExecuted.setSuccess(null);
assertTrue(isStreamIdValid(stream.id())); }
listenerExecuted.setSuccess(null); );
}
}
);
ByteBuf data = Unpooled.buffer().writeZero(100); ByteBuf data = Unpooled.buffer().writeZero(100);
ChannelFuture f = channel.writeAndFlush(new DefaultHttp2DataFrame(data).stream(stream)); ChannelFuture f = channel.writeAndFlush(new DefaultHttp2DataFrame(data).stream(stream));
assertTrue(f.isSuccess()); assertTrue(f.isSuccess());
@ -735,12 +732,9 @@ public class Http2FrameCodecTest {
Http2FrameStream idleStream = frameCodec.newStream(); Http2FrameStream idleStream = frameCodec.newStream();
final Set<Http2FrameStream> activeStreams = new HashSet<>(); final Set<Http2FrameStream> activeStreams = new HashSet<>();
frameCodec.forEachActiveStream(new Http2FrameStreamVisitor() { frameCodec.forEachActiveStream(stream -> {
@Override activeStreams.add(stream);
public boolean visit(Http2FrameStream stream) { return true;
activeStreams.add(stream);
return true;
}
}); });
assertEquals(2, activeStreams.size()); assertEquals(2, activeStreams.size());
@ -758,13 +752,10 @@ public class Http2FrameCodecTest {
final AtomicBoolean listenerExecuted = new AtomicBoolean(); final AtomicBoolean listenerExecuted = new AtomicBoolean();
channel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()).stream(stream2)) channel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()).stream(stream2))
.addListener(new ChannelFutureListener() { .addListener((ChannelFutureListener) future -> {
@Override assertTrue(future.isSuccess());
public void operationComplete(ChannelFuture future) throws Exception { assertEquals(State.OPEN, stream2.state());
assertTrue(future.isSuccess()); listenerExecuted.set(true);
assertEquals(State.OPEN, stream2.state());
listenerExecuted.set(true);
}
}); });
assertTrue(listenerExecuted.get()); assertTrue(listenerExecuted.get());
@ -795,15 +786,12 @@ public class Http2FrameCodecTest {
// Simulate consuming the frame and update the flow-controller. // Simulate consuming the frame and update the flow-controller.
Http2DataFrame data = (Http2DataFrame) msg; Http2DataFrame data = (Http2DataFrame) msg;
ctx.writeAndFlush(new DefaultHttp2WindowUpdateFrame(data.initialFlowControlledBytes()) ctx.writeAndFlush(new DefaultHttp2WindowUpdateFrame(data.initialFlowControlledBytes())
.stream(data.stream())).addListener(new ChannelFutureListener() { .stream(data.stream())).addListener((ChannelFutureListener) future -> {
@Override Throwable cause = future.cause();
public void operationComplete(ChannelFuture future) throws Exception { if (cause != null) {
Throwable cause = future.cause(); ctx.fireExceptionCaught(cause);
if (cause != null) { }
ctx.fireExceptionCaught(cause); });
}
}
});
} }
ReferenceCountUtil.release(msg); ReferenceCountUtil.release(msg);
} }

View File

@ -97,24 +97,10 @@ public class Http2FrameRoundtripTest {
when(ctx.alloc()).thenReturn(alloc); when(ctx.alloc()).thenReturn(alloc);
when(ctx.executor()).thenReturn(executor); when(ctx.executor()).thenReturn(executor);
when(ctx.channel()).thenReturn(channel); when(ctx.channel()).thenReturn(channel);
doAnswer(new Answer<ByteBuf>() { doAnswer((Answer<ByteBuf>) in -> Unpooled.buffer()).when(alloc).buffer();
@Override doAnswer((Answer<ByteBuf>) in -> Unpooled.buffer((Integer) in.getArguments()[0])).when(alloc).buffer(anyInt());
public ByteBuf answer(InvocationOnMock in) throws Throwable { doAnswer((Answer<ChannelPromise>) invocation ->
return Unpooled.buffer(); new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).when(ctx).newPromise();
}
}).when(alloc).buffer();
doAnswer(new Answer<ByteBuf>() {
@Override
public ByteBuf answer(InvocationOnMock in) throws Throwable {
return Unpooled.buffer((Integer) in.getArguments()[0]);
}
}).when(alloc).buffer(anyInt());
doAnswer(new Answer<ChannelPromise>() {
@Override
public ChannelPromise answer(InvocationOnMock invocation) throws Throwable {
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE);
}
}).when(ctx).newPromise();
writer = new DefaultHttp2FrameWriter(new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE, newTestEncoder())); writer = new DefaultHttp2FrameWriter(new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE, newTestEncoder()));
reader = new DefaultHttp2FrameReader(new DefaultHttp2HeadersDecoder(false, newTestDecoder())); reader = new DefaultHttp2FrameReader(new DefaultHttp2HeadersDecoder(false, newTestDecoder()));

View File

@ -245,12 +245,7 @@ public class Http2MultiplexCodecTest {
frameInboundWriter.writeInboundData(channel.stream().id(), tenBytes, 0, true); frameInboundWriter.writeInboundData(channel.stream().id(), tenBytes, 0, true);
// Verify we marked the bytes as consumed // Verify we marked the bytes as consumed
verify(flowController).consumeBytes(argThat(new ArgumentMatcher<Http2Stream>() { verify(flowController).consumeBytes(argThat(http2Stream -> http2Stream.id() == channel.stream().id()), eq(10));
@Override
public boolean matches(Http2Stream http2Stream) {
return http2Stream.id() == channel.stream().id();
}
}), eq(10));
// headers and data frame // headers and data frame
verifyFramesMultiplexedToCorrectChannel(channel, handler, 2); verifyFramesMultiplexedToCorrectChannel(channel, handler, 2);
@ -459,13 +454,9 @@ public class Http2MultiplexCodecTest {
Http2Headers headers = new DefaultHttp2Headers(); Http2Headers headers = new DefaultHttp2Headers();
when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(), when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(),
eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(), eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(),
any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(8)).setFailure(
public ChannelFuture answer(InvocationOnMock invocationOnMock) { new StreamException(childChannel.stream().id(), Http2Error.STREAM_CLOSED, "Stream Closed")));
return ((ChannelPromise) invocationOnMock.getArgument(8)).setFailure(
new StreamException(childChannel.stream().id(), Http2Error.STREAM_CLOSED, "Stream Closed"));
}
});
ChannelFuture future = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers())); ChannelFuture future = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()));
parentChannel.flush(); parentChannel.flush();
@ -521,13 +512,9 @@ public class Http2MultiplexCodecTest {
Http2Headers headers = new DefaultHttp2Headers(); Http2Headers headers = new DefaultHttp2Headers();
when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(), when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(),
eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(), eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(),
any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(8)).setFailure(
public ChannelFuture answer(InvocationOnMock invocationOnMock) { new Http2NoMoreStreamIdsException()));
return ((ChannelPromise) invocationOnMock.getArgument(8)).setFailure(
new Http2NoMoreStreamIdsException());
}
});
ChannelFuture future = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(headers)); ChannelFuture future = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(headers));
parentChannel.flush(); parentChannel.flush();
@ -554,12 +541,9 @@ public class Http2MultiplexCodecTest {
// Create a promise before actually doing the close, because otherwise we would be adding a listener to a future // Create a promise before actually doing the close, because otherwise we would be adding a listener to a future
// that is already completed because we are using EmbeddedChannel which executes code in the JUnit thread. // that is already completed because we are using EmbeddedChannel which executes code in the JUnit thread.
ChannelPromise p = childChannel.newPromise(); ChannelPromise p = childChannel.newPromise();
p.addListener(new ChannelFutureListener() { p.addListener((ChannelFutureListener) future -> {
@Override channelOpen.set(future.channel().isOpen());
public void operationComplete(ChannelFuture future) { channelActive.set(future.channel().isActive());
channelOpen.set(future.channel().isOpen());
channelActive.set(future.channel().isActive());
}
}); });
childChannel.close(p).syncUninterruptibly(); childChannel.close(p).syncUninterruptibly();
@ -579,12 +563,9 @@ public class Http2MultiplexCodecTest {
final AtomicBoolean channelOpen = new AtomicBoolean(true); final AtomicBoolean channelOpen = new AtomicBoolean(true);
final AtomicBoolean channelActive = new AtomicBoolean(true); final AtomicBoolean channelActive = new AtomicBoolean(true);
childChannel.closeFuture().addListener(new ChannelFutureListener() { childChannel.closeFuture().addListener((ChannelFutureListener) future -> {
@Override channelOpen.set(future.channel().isOpen());
public void operationComplete(ChannelFuture future) { channelActive.set(future.channel().isActive());
channelOpen.set(future.channel().isOpen());
channelActive.set(future.channel().isActive());
}
}); });
childChannel.close().syncUninterruptibly(); childChannel.close().syncUninterruptibly();
@ -609,23 +590,17 @@ public class Http2MultiplexCodecTest {
Http2Headers headers = new DefaultHttp2Headers(); Http2Headers headers = new DefaultHttp2Headers();
when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(), when(frameWriter.writeHeaders(eqMultiplexCodecCtx(), anyInt(),
eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(), eq(headers), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(),
any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock -> {
@Override ChannelPromise promise = invocationOnMock.getArgument(8);
public ChannelFuture answer(InvocationOnMock invocationOnMock) { writePromises.offer(promise);
ChannelPromise promise = invocationOnMock.getArgument(8); return promise;
writePromises.offer(promise); });
return promise;
}
});
ChannelFuture f = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(headers)); ChannelFuture f = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(headers));
assertFalse(f.isDone()); assertFalse(f.isDone());
f.addListener(new ChannelFutureListener() { f.addListener((ChannelFutureListener) future -> {
@Override channelOpen.set(future.channel().isOpen());
public void operationComplete(ChannelFuture future) throws Exception { channelActive.set(future.channel().isActive());
channelOpen.set(future.channel().isOpen());
channelActive.set(future.channel().isActive());
}
}); });
ChannelPromise first = writePromises.poll(); ChannelPromise first = writePromises.poll();
@ -794,12 +769,9 @@ public class Http2MultiplexCodecTest {
public void endOfStreamDoesNotDiscardData() { public void endOfStreamDoesNotDiscardData() {
AtomicInteger numReads = new AtomicInteger(1); AtomicInteger numReads = new AtomicInteger(1);
final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean(); final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean();
Consumer<ChannelHandlerContext> ctxConsumer = new Consumer<ChannelHandlerContext>() { Consumer<ChannelHandlerContext> ctxConsumer = obj -> {
@Override if (shouldDisableAutoRead.get()) {
public void accept(ChannelHandlerContext obj) { obj.channel().config().setAutoRead(false);
if (shouldDisableAutoRead.get()) {
obj.channel().config().setAutoRead(false);
}
} }
}; };
LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer); LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer);
@ -859,13 +831,10 @@ public class Http2MultiplexCodecTest {
AtomicInteger numReads = new AtomicInteger(1); AtomicInteger numReads = new AtomicInteger(1);
final AtomicInteger channelReadCompleteCount = new AtomicInteger(0); final AtomicInteger channelReadCompleteCount = new AtomicInteger(0);
final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean(); final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean();
Consumer<ChannelHandlerContext> ctxConsumer = new Consumer<ChannelHandlerContext>() { Consumer<ChannelHandlerContext> ctxConsumer = obj -> {
@Override channelReadCompleteCount.incrementAndGet();
public void accept(ChannelHandlerContext obj) { if (shouldDisableAutoRead.get()) {
channelReadCompleteCount.incrementAndGet(); obj.channel().config().setAutoRead(false);
if (shouldDisableAutoRead.get()) {
obj.channel().config().setAutoRead(false);
}
} }
}; };
LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer); LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer);
@ -922,13 +891,10 @@ public class Http2MultiplexCodecTest {
final AtomicInteger numReads = new AtomicInteger(1); final AtomicInteger numReads = new AtomicInteger(1);
final AtomicInteger channelReadCompleteCount = new AtomicInteger(0); final AtomicInteger channelReadCompleteCount = new AtomicInteger(0);
final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean(); final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean();
Consumer<ChannelHandlerContext> ctxConsumer = new Consumer<ChannelHandlerContext>() { Consumer<ChannelHandlerContext> ctxConsumer = obj -> {
@Override channelReadCompleteCount.incrementAndGet();
public void accept(ChannelHandlerContext obj) { if (shouldDisableAutoRead.get()) {
channelReadCompleteCount.incrementAndGet(); obj.channel().config().setAutoRead(false);
if (shouldDisableAutoRead.get()) {
obj.channel().config().setAutoRead(false);
}
} }
}; };
final LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer); final LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer);

View File

@ -70,14 +70,11 @@ public final class Http2TestUtil {
* Runs the given operation within the event loop thread of the given {@link Channel}. * Runs the given operation within the event loop thread of the given {@link Channel}.
*/ */
static void runInChannel(Channel channel, final Http2Runnable runnable) { static void runInChannel(Channel channel, final Http2Runnable runnable) {
channel.eventLoop().execute(new Runnable() { channel.eventLoop().execute(() -> {
@Override try {
public void run() { runnable.run();
try { } catch (Http2Exception e) {
runnable.run(); throw new RuntimeException(e);
} catch (Http2Exception e) {
throw new RuntimeException(e);
}
} }
}); });
} }
@ -477,12 +474,9 @@ public final class Http2TestUtil {
public ChannelPromise unvoid() { public ChannelPromise unvoid() {
ChannelPromise promise = ChannelPromise promise =
new DefaultChannelPromise(channel, ImmediateEventExecutor.INSTANCE); new DefaultChannelPromise(channel, ImmediateEventExecutor.INSTANCE);
promise.addListener(new ChannelFutureListener() { promise.addListener((ChannelFutureListener) future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { channel().pipeline().fireExceptionCaught(future.cause());
if (!future.isSuccess()) {
channel().pipeline().fireExceptionCaught(future.cause());
}
} }
}); });
return promise; return promise;
@ -575,103 +569,63 @@ public final class Http2TestUtil {
final ConcurrentLinkedQueue<ByteBuf> buffers = new ConcurrentLinkedQueue<>(); final ConcurrentLinkedQueue<ByteBuf> buffers = new ConcurrentLinkedQueue<>();
Http2FrameWriter frameWriter = Mockito.mock(Http2FrameWriter.class); Http2FrameWriter frameWriter = Mockito.mock(Http2FrameWriter.class);
doAnswer(new Answer() { doAnswer(invocationOnMock -> {
@Override for (;;) {
public Object answer(InvocationOnMock invocationOnMock) { ByteBuf buf = buffers.poll();
for (;;) { if (buf == null) {
ByteBuf buf = buffers.poll(); break;
if (buf == null) {
break;
}
buf.release();
} }
return null; buf.release();
} }
return null;
}).when(frameWriter).close(); }).when(frameWriter).close();
when(frameWriter.configuration()).thenReturn(configuration); when(frameWriter.configuration()).thenReturn(configuration);
when(frameWriter.writeSettings(any(ChannelHandlerContext.class), any(Http2Settings.class), when(frameWriter.writeSettings(any(ChannelHandlerContext.class), any(Http2Settings.class),
any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(2)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(2)).setSuccess();
}
});
when(frameWriter.writeSettingsAck(any(ChannelHandlerContext.class), any(ChannelPromise.class))) when(frameWriter.writeSettingsAck(any(ChannelHandlerContext.class), any(ChannelPromise.class)))
.thenAnswer(new Answer<ChannelFuture>() { .thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(1)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(1)).setSuccess();
}
});
when(frameWriter.writeGoAway(any(ChannelHandlerContext.class), anyInt(), when(frameWriter.writeGoAway(any(ChannelHandlerContext.class), anyInt(),
anyLong(), any(ByteBuf.class), any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { anyLong(), any(ByteBuf.class), any(ChannelPromise.class))).thenAnswer(invocationOnMock -> {
@Override buffers.offer((ByteBuf) invocationOnMock.getArgument(3));
public ChannelFuture answer(InvocationOnMock invocationOnMock) { return ((ChannelPromise) invocationOnMock.getArgument(4)).setSuccess();
buffers.offer((ByteBuf) invocationOnMock.getArgument(3)); });
return ((ChannelPromise) invocationOnMock.getArgument(4)).setSuccess();
}
});
when(frameWriter.writeHeaders(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class), anyInt(), when(frameWriter.writeHeaders(any(ChannelHandlerContext.class), anyInt(), any(Http2Headers.class), anyInt(),
anyBoolean(), any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { anyBoolean(), any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
}
});
when(frameWriter.writeHeaders(any(ChannelHandlerContext.class), anyInt(), when(frameWriter.writeHeaders(any(ChannelHandlerContext.class), anyInt(),
any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(), any(Http2Headers.class), anyInt(), anyShort(), anyBoolean(), anyInt(), anyBoolean(),
any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(8)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(8)).setSuccess();
}
});
when(frameWriter.writeData(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), anyInt(), when(frameWriter.writeData(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), anyInt(),
anyBoolean(), any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { anyBoolean(), any(ChannelPromise.class))).thenAnswer(invocationOnMock -> {
@Override buffers.offer((ByteBuf) invocationOnMock.getArgument(2));
public ChannelFuture answer(InvocationOnMock invocationOnMock) { return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
buffers.offer((ByteBuf) invocationOnMock.getArgument(2)); });
return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
}
});
when(frameWriter.writeRstStream(any(ChannelHandlerContext.class), anyInt(), when(frameWriter.writeRstStream(any(ChannelHandlerContext.class), anyInt(),
anyLong(), any(ChannelPromise.class))).thenAnswer(new Answer<ChannelFuture>() { anyLong(), any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(3)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(3)).setSuccess();
}
});
when(frameWriter.writeWindowUpdate(any(ChannelHandlerContext.class), anyInt(), anyInt(), when(frameWriter.writeWindowUpdate(any(ChannelHandlerContext.class), anyInt(), anyInt(),
any(ChannelPromise.class))).then(new Answer<ChannelFuture>() { any(ChannelPromise.class))).then((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(3)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(3)).setSuccess();
}
});
when(frameWriter.writePushPromise(any(ChannelHandlerContext.class), anyInt(), anyInt(), any(Http2Headers.class), when(frameWriter.writePushPromise(any(ChannelHandlerContext.class), anyInt(), anyInt(), any(Http2Headers.class),
anyInt(), anyChannelPromise())).thenAnswer(new Answer<ChannelFuture>() { anyInt(), anyChannelPromise())).thenAnswer((Answer<ChannelFuture>) invocationOnMock ->
@Override ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess());
public ChannelFuture answer(InvocationOnMock invocationOnMock) {
return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
}
});
when(frameWriter.writeFrame(any(ChannelHandlerContext.class), anyByte(), anyInt(), any(Http2Flags.class), when(frameWriter.writeFrame(any(ChannelHandlerContext.class), anyByte(), anyInt(), any(Http2Flags.class),
any(ByteBuf.class), anyChannelPromise())).thenAnswer(new Answer<ChannelFuture>() { any(ByteBuf.class), anyChannelPromise())).thenAnswer(invocationOnMock -> {
@Override buffers.offer((ByteBuf) invocationOnMock.getArgument(4));
public ChannelFuture answer(InvocationOnMock invocationOnMock) { return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
buffers.offer((ByteBuf) invocationOnMock.getArgument(4)); });
return ((ChannelPromise) invocationOnMock.getArgument(5)).setSuccess();
}
});
return frameWriter; return frameWriter;
} }

View File

@ -337,12 +337,9 @@ public class HttpToHttp2ConnectionHandlerTest {
public void testRequestWithBody() throws Exception { public void testRequestWithBody() throws Exception {
final String text = "foooooogoooo"; final String text = "foooooogoooo";
final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>()); final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>());
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) in -> {
@Override receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
public Void answer(InvocationOnMock in) throws Throwable { return null;
receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
return null;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3),
any(ByteBuf.class), eq(0), eq(true)); any(ByteBuf.class), eq(0), eq(true));
bootstrapEnv(3, 1, 0); bootstrapEnv(3, 1, 0);
@ -380,12 +377,9 @@ public class HttpToHttp2ConnectionHandlerTest {
public void testRequestWithBodyAndTrailingHeaders() throws Exception { public void testRequestWithBodyAndTrailingHeaders() throws Exception {
final String text = "foooooogoooo"; final String text = "foooooogoooo";
final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>()); final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>());
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) in -> {
@Override receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
public Void answer(InvocationOnMock in) throws Throwable { return null;
receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
return null;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3),
any(ByteBuf.class), eq(0), eq(false)); any(ByteBuf.class), eq(0), eq(false));
bootstrapEnv(4, 1, 1); bootstrapEnv(4, 1, 1);
@ -432,12 +426,9 @@ public class HttpToHttp2ConnectionHandlerTest {
final String text = "foooooo"; final String text = "foooooo";
final String text2 = "goooo"; final String text2 = "goooo";
final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>()); final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<>());
doAnswer(new Answer<Void>() { doAnswer((Answer<Void>) in -> {
@Override receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
public Void answer(InvocationOnMock in) throws Throwable { return null;
receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
return null;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3),
any(ByteBuf.class), eq(0), eq(false)); any(ByteBuf.class), eq(0), eq(false));
bootstrapEnv(4, 1, 1); bootstrapEnv(4, 1, 1);

View File

@ -148,12 +148,9 @@ public class InboundHttp2ToHttpAdapterTest {
final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")). final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).
scheme(new AsciiString("https")).authority(new AsciiString("example.org")) scheme(new AsciiString("https")).authority(new AsciiString("example.org"))
.path(new AsciiString("/some/path/resource2")); .path(new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -184,12 +181,9 @@ public class InboundHttp2ToHttpAdapterTest {
.add(HttpHeaderNames.COOKIE, "a=b") .add(HttpHeaderNames.COOKIE, "a=b")
.add(HttpHeaderNames.COOKIE, "c=d") .add(HttpHeaderNames.COOKIE, "c=d")
.add(HttpHeaderNames.COOKIE, "e=f"); .add(HttpHeaderNames.COOKIE, "e=f");
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -219,12 +213,9 @@ public class InboundHttp2ToHttpAdapterTest {
.path(new AsciiString("/some/path/resource2")) .path(new AsciiString("/some/path/resource2"))
.add(HttpHeaderNames.COOKIE, "a=b; c=d") .add(HttpHeaderNames.COOKIE, "a=b; c=d")
.add(HttpHeaderNames.COOKIE, "e=f"); .add(HttpHeaderNames.COOKIE, "e=f");
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -246,12 +237,9 @@ public class InboundHttp2ToHttpAdapterTest {
.path(new AsciiString("/some/path/resource2")) .path(new AsciiString("/some/path/resource2"))
.add(new AsciiString("çã".getBytes(CharsetUtil.UTF_8)), .add(new AsciiString("çã".getBytes(CharsetUtil.UTF_8)),
new AsciiString("Ãã".getBytes(CharsetUtil.UTF_8))); new AsciiString("Ãã".getBytes(CharsetUtil.UTF_8)));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitResponses(); awaitResponses();
assertTrue(isStreamError(clientException)); assertTrue(isStreamError(clientException));
@ -271,14 +259,11 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16); httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path( final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
new AsciiString("/some/path/resource2")); new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true, clientChannel.flush();
newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -305,17 +290,14 @@ public class InboundHttp2ToHttpAdapterTest {
final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path( final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
new AsciiString("/some/path/resource2")); new AsciiString("/some/path/resource2"));
final int midPoint = text.length() / 2; final int midPoint = text.length() / 2;
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientHandler.encoder().writeData(
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); ctxClient(), 3, content.retainedSlice(0, midPoint), 0, false, newPromiseClient());
clientHandler.encoder().writeData( clientHandler.encoder().writeData(
ctxClient(), 3, content.retainedSlice(0, midPoint), 0, false, newPromiseClient()); ctxClient(), 3, content.retainedSlice(midPoint, text.length() - midPoint),
clientHandler.encoder().writeData( 0, true, newPromiseClient());
ctxClient(), 3, content.retainedSlice(midPoint, text.length() - midPoint), clientChannel.flush();
0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -341,15 +323,12 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16); httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path( final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
new AsciiString("/some/path/resource2")); new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient()); clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient()); clientChannel.flush();
clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -383,15 +362,12 @@ public class InboundHttp2ToHttpAdapterTest {
.set(new AsciiString("foo"), new AsciiString("goo")) .set(new AsciiString("foo"), new AsciiString("goo"))
.set(new AsciiString("foo2"), new AsciiString("goo2")) .set(new AsciiString("foo2"), new AsciiString("goo2"))
.add(new AsciiString("foo2"), new AsciiString("goo3")); .add(new AsciiString("foo2"), new AsciiString("goo3"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, false,
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, false, clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers2, 0, true, newPromiseClient());
newPromiseClient()); clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers2, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -428,19 +404,16 @@ public class InboundHttp2ToHttpAdapterTest {
new AsciiString("/some/path/resource")); new AsciiString("/some/path/resource"));
final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(new AsciiString("PUT")).path( final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
new AsciiString("/some/path/resource2")); new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientHandler.encoder().writeHeaders(ctxClient(), 5, http2Headers2, 3, (short) 123, true, 0,
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); false, newPromiseClient());
clientHandler.encoder().writeHeaders(ctxClient(), 5, http2Headers2, 3, (short) 123, true, 0, clientChannel.flush(); // Headers are queued in the flow controller and so flush them.
false, newPromiseClient()); clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
clientChannel.flush(); // Headers are queued in the flow controller and so flush them. newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true, clientHandler.encoder().writeData(ctxClient(), 5, content2.retainedDuplicate(), 0, true,
newPromiseClient()); newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 5, content2.retainedDuplicate(), 0, true, clientChannel.flush();
newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> httpObjectCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> httpObjectCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -485,12 +458,9 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16); httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
final Http2Headers http2Headers3 = new DefaultHttp2Headers().method(new AsciiString("GET")) final Http2Headers http2Headers3 = new DefaultHttp2Headers().method(new AsciiString("GET"))
.path(new AsciiString("/push/test")); .path(new AsciiString("/push/test"));
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers3, 0, true, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers3, 0, true, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -507,17 +477,14 @@ public class InboundHttp2ToHttpAdapterTest {
final Http2Headers http2Headers2 = new DefaultHttp2Headers() final Http2Headers http2Headers2 = new DefaultHttp2Headers()
.scheme(new AsciiString("https")) .scheme(new AsciiString("https"))
.authority(new AsciiString("example.org")); .authority(new AsciiString("example.org"));
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override serverHandler.encoder().writeHeaders(ctxServer(), 3, http2Headers, 0, false, newPromiseServer());
public void run() throws Http2Exception { serverHandler.encoder().writePushPromise(ctxServer(), 3, 2, http2Headers2, 0, newPromiseServer());
serverHandler.encoder().writeHeaders(ctxServer(), 3, http2Headers, 0, false, newPromiseServer()); serverHandler.encoder().writeData(ctxServer(), 3, content.retainedDuplicate(), 0, true,
serverHandler.encoder().writePushPromise(ctxServer(), 3, 2, http2Headers2, 0, newPromiseServer()); newPromiseServer());
serverHandler.encoder().writeData(ctxServer(), 3, content.retainedDuplicate(), 0, true, serverHandler.encoder().writeData(ctxServer(), 5, content2.retainedDuplicate(), 0, true,
newPromiseServer()); newPromiseServer());
serverHandler.encoder().writeData(ctxServer(), 5, content2.retainedDuplicate(), 0, true, serverConnectedChannel.flush();
newPromiseServer());
serverConnectedChannel.flush();
}
}); });
awaitResponses(); awaitResponses();
ArgumentCaptor<FullHttpMessage> responseCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); ArgumentCaptor<FullHttpMessage> responseCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
@ -553,12 +520,9 @@ public class InboundHttp2ToHttpAdapterTest {
final FullHttpMessage response2 = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); final FullHttpMessage response2 = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
try { try {
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
public void run() throws Http2Exception { clientChannel.flush();
clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests(); awaitRequests();
@ -566,26 +530,20 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3); httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0); httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
final Http2Headers http2HeadersResponse = new DefaultHttp2Headers().status(new AsciiString("100")); final Http2Headers http2HeadersResponse = new DefaultHttp2Headers().status(new AsciiString("100"));
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse, 0, false,
public void run() throws Http2Exception { newPromiseServer());
serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse, 0, false, serverConnectedChannel.flush();
newPromiseServer());
serverConnectedChannel.flush();
}
}); });
awaitResponses(); awaitResponses();
httpHeaders = request2.headers(); httpHeaders = request2.headers();
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length()); httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
httpHeaders.remove(HttpHeaderNames.EXPECT); httpHeaders.remove(HttpHeaderNames.EXPECT);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeData(ctxClient(), 3, payload.retainedDuplicate(), 0, true,
public void run() { newPromiseClient());
clientHandler.encoder().writeData(ctxClient(), 3, payload.retainedDuplicate(), 0, true, clientChannel.flush();
newPromiseClient());
clientChannel.flush();
}
}); });
awaitRequests2(); awaitRequests2();
@ -595,13 +553,10 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16); httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
final Http2Headers http2HeadersResponse2 = new DefaultHttp2Headers().status(new AsciiString("200")); final Http2Headers http2HeadersResponse2 = new DefaultHttp2Headers().status(new AsciiString("200"));
runInChannel(serverConnectedChannel, new Http2Runnable() { runInChannel(serverConnectedChannel, () -> {
@Override serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse2, 0, true,
public void run() throws Http2Exception { newPromiseServer());
serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse2, 0, true, serverConnectedChannel.flush();
newPromiseServer());
serverConnectedChannel.flush();
}
}); });
awaitResponses2(); awaitResponses2();
@ -633,12 +588,9 @@ public class InboundHttp2ToHttpAdapterTest {
public void propagateSettings() throws Exception { public void propagateSettings() throws Exception {
boostrapEnv(1, 1, 2); boostrapEnv(1, 1, 2);
final Http2Settings settings = new Http2Settings().pushEnabled(true); final Http2Settings settings = new Http2Settings().pushEnabled(true);
runInChannel(clientChannel, new Http2Runnable() { runInChannel(clientChannel, () -> {
@Override clientHandler.encoder().writeSettings(ctxClient(), settings, newPromiseClient());
public void run() { clientChannel.flush();
clientHandler.encoder().writeSettings(ctxClient(), settings, newPromiseClient());
clientChannel.flush();
}
}); });
assertTrue(settingsLatch.await(5, SECONDS)); assertTrue(settingsLatch.await(5, SECONDS));
ArgumentCaptor<Http2Settings> settingsCaptor = ArgumentCaptor.forClass(Http2Settings.class); ArgumentCaptor<Http2Settings> settingsCaptor = ArgumentCaptor.forClass(Http2Settings.class);

View File

@ -46,10 +46,7 @@ public class LastInboundHandler extends ChannelDuplexHandler {
void accept(T obj); void accept(T obj);
} }
private static final Consumer<Object> NOOP_CONSUMER = new Consumer<Object>() { private static final Consumer<Object> NOOP_CONSUMER = obj -> {
@Override
public void accept(Object obj) {
}
}; };
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -130,12 +130,7 @@ public class StreamBufferingEncoderTest {
when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT); when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT);
when(channel.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT); when(channel.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT);
when(executor.inEventLoop()).thenReturn(true); when(executor.inEventLoop()).thenReturn(true);
doAnswer(new Answer<ChannelPromise>() { doAnswer((Answer<ChannelPromise>) invocation -> newPromise()).when(ctx).newPromise();
@Override
public ChannelPromise answer(InvocationOnMock invocation) throws Throwable {
return newPromise();
}
}).when(ctx).newPromise();
when(ctx.executor()).thenReturn(executor); when(ctx.executor()).thenReturn(executor);
when(channel.isActive()).thenReturn(false); when(channel.isActive()).thenReturn(false);
when(channel.config()).thenReturn(config); when(channel.config()).thenReturn(config);
@ -519,17 +514,14 @@ public class StreamBufferingEncoderTest {
} }
private Answer<ChannelFuture> successAnswer() { private Answer<ChannelFuture> successAnswer() {
return new Answer<ChannelFuture>() { return invocation -> {
@Override for (Object a : invocation.getArguments()) {
public ChannelFuture answer(InvocationOnMock invocation) throws Throwable { ReferenceCountUtil.safeRelease(a);
for (Object a : invocation.getArguments()) {
ReferenceCountUtil.safeRelease(a);
}
ChannelPromise future = newPromise();
future.setSuccess();
return future;
} }
ChannelPromise future = newPromise();
future.setSuccess();
return future;
}; };
} }

View File

@ -83,17 +83,14 @@ public class UniformStreamByteDistributorTest {
} }
private Answer<Void> writeAnswer() { private Answer<Void> writeAnswer() {
return new Answer<Void>() { return in -> {
@Override Http2Stream stream = in.getArgument(0);
public Void answer(InvocationOnMock in) throws Throwable { int numBytes = in.getArgument(1);
Http2Stream stream = in.getArgument(0); TestStreamByteDistributorStreamState state = stateMap.get(stream.id());
int numBytes = in.getArgument(1); state.pendingBytes -= numBytes;
TestStreamByteDistributorStreamState state = stateMap.get(stream.id()); state.hasFrame = state.pendingBytes > 0;
state.pendingBytes -= numBytes; distributor.updateStreamableBytes(state);
state.hasFrame = state.pendingBytes > 0; return null;
distributor.updateStreamableBytes(state);
return null;
}
}; };
} }

View File

@ -79,13 +79,10 @@ public class WeightedFairQueueByteDistributorDependencyTreeTest extends
final Http2Stream streamB = connection.local().createStream(5, false); final Http2Stream streamB = connection.local().createStream(5, false);
final Http2Stream streamC = connection.local().createStream(7, false); final Http2Stream streamC = connection.local().createStream(7, false);
setPriority(streamB.id(), streamA.id(), DEFAULT_PRIORITY_WEIGHT, false); setPriority(streamB.id(), streamA.id(), DEFAULT_PRIORITY_WEIGHT, false);
connection.forEachActiveStream(new Http2StreamVisitor() { connection.forEachActiveStream(stream -> {
@Override streamA.close();
public boolean visit(Http2Stream stream) throws Http2Exception { setPriority(streamB.id(), streamC.id(), DEFAULT_PRIORITY_WEIGHT, false);
streamA.close(); return true;
setPriority(streamB.id(), streamC.id(), DEFAULT_PRIORITY_WEIGHT, false);
return true;
}
}); });
} }

View File

@ -29,33 +29,30 @@ import io.netty.util.NetUtil;
*/ */
public interface Socks5AddressEncoder { public interface Socks5AddressEncoder {
Socks5AddressEncoder DEFAULT = new Socks5AddressEncoder() { Socks5AddressEncoder DEFAULT = (addrType, addrValue, out) -> {
@Override final byte typeVal = addrType.byteValue();
public void encodeAddress(Socks5AddressType addrType, String addrValue, ByteBuf out) throws Exception { if (typeVal == Socks5AddressType.IPv4.byteValue()) {
final byte typeVal = addrType.byteValue(); if (addrValue != null) {
if (typeVal == Socks5AddressType.IPv4.byteValue()) { out.writeBytes(NetUtil.createByteArrayFromIpAddressString(addrValue));
if (addrValue != null) {
out.writeBytes(NetUtil.createByteArrayFromIpAddressString(addrValue));
} else {
out.writeInt(0);
}
} else if (typeVal == Socks5AddressType.DOMAIN.byteValue()) {
if (addrValue != null) {
out.writeByte(addrValue.length());
out.writeCharSequence(addrValue, CharsetUtil.US_ASCII);
} else {
out.writeByte(0);
}
} else if (typeVal == Socks5AddressType.IPv6.byteValue()) {
if (addrValue != null) {
out.writeBytes(NetUtil.createByteArrayFromIpAddressString(addrValue));
} else {
out.writeLong(0);
out.writeLong(0);
}
} else { } else {
throw new EncoderException("unsupported addrType: " + (addrType.byteValue() & 0xFF)); out.writeInt(0);
} }
} else if (typeVal == Socks5AddressType.DOMAIN.byteValue()) {
if (addrValue != null) {
out.writeByte(addrValue.length());
out.writeCharSequence(addrValue, CharsetUtil.US_ASCII);
} else {
out.writeByte(0);
}
} else if (typeVal == Socks5AddressType.IPv6.byteValue()) {
if (addrValue != null) {
out.writeBytes(NetUtil.createByteArrayFromIpAddressString(addrValue));
} else {
out.writeLong(0);
out.writeLong(0);
}
} else {
throw new EncoderException("unsupported addrType: " + (addrType.byteValue() & 0xFF));
} }
}; };

View File

@ -72,31 +72,28 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
/** /**
* Cumulate {@link ByteBuf}s by merge them into one {@link ByteBuf}'s, using memory copies. * Cumulate {@link ByteBuf}s by merge them into one {@link ByteBuf}'s, using memory copies.
*/ */
public static final Cumulator MERGE_CUMULATOR = new Cumulator() { public static final Cumulator MERGE_CUMULATOR = (alloc, cumulation, in) -> {
@Override try {
public ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in) { final ByteBuf buffer;
try { if (cumulation.writerIndex() > cumulation.maxCapacity() - in.readableBytes()
final ByteBuf buffer; || cumulation.refCnt() > 1 || cumulation.isReadOnly()) {
if (cumulation.writerIndex() > cumulation.maxCapacity() - in.readableBytes() // Expand cumulation (by replace it) when either there is not more room in the buffer
|| cumulation.refCnt() > 1 || cumulation.isReadOnly()) { // or if the refCnt is greater then 1 which may happen when the user use slice().retain() or
// Expand cumulation (by replace it) when either there is not more room in the buffer // duplicate().retain() or if its read-only.
// or if the refCnt is greater then 1 which may happen when the user use slice().retain() or //
// duplicate().retain() or if its read-only. // See:
// // - https://github.com/netty/netty/issues/2327
// See: // - https://github.com/netty/netty/issues/1764
// - https://github.com/netty/netty/issues/2327 buffer = expandCumulation(alloc, cumulation, in.readableBytes());
// - https://github.com/netty/netty/issues/1764 } else {
buffer = expandCumulation(alloc, cumulation, in.readableBytes()); buffer = cumulation;
} else {
buffer = cumulation;
}
buffer.writeBytes(in);
return buffer;
} finally {
// We must release in in all cases as otherwise it may produce a leak if writeBytes(...) throw
// for whatever release (for example because of OutOfMemoryError)
in.release();
} }
buffer.writeBytes(in);
return buffer;
} finally {
// We must release in in all cases as otherwise it may produce a leak if writeBytes(...) throw
// for whatever release (for example because of OutOfMemoryError)
in.release();
} }
}; };
@ -105,39 +102,36 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
* Be aware that {@link CompositeByteBuf} use a more complex indexing implementation so depending on your use-case * Be aware that {@link CompositeByteBuf} use a more complex indexing implementation so depending on your use-case
* and the decoder implementation this may be slower then just use the {@link #MERGE_CUMULATOR}. * and the decoder implementation this may be slower then just use the {@link #MERGE_CUMULATOR}.
*/ */
public static final Cumulator COMPOSITE_CUMULATOR = new Cumulator() { public static final Cumulator COMPOSITE_CUMULATOR = (alloc, cumulation, in) -> {
@Override ByteBuf buffer;
public ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in) { try {
ByteBuf buffer; if (cumulation.refCnt() > 1) {
try { // Expand cumulation (by replace it) when the refCnt is greater then 1 which may happen when the
if (cumulation.refCnt() > 1) { // user use slice().retain() or duplicate().retain().
// Expand cumulation (by replace it) when the refCnt is greater then 1 which may happen when the //
// user use slice().retain() or duplicate().retain(). // See:
// // - https://github.com/netty/netty/issues/2327
// See: // - https://github.com/netty/netty/issues/1764
// - https://github.com/netty/netty/issues/2327 buffer = expandCumulation(alloc, cumulation, in.readableBytes());
// - https://github.com/netty/netty/issues/1764 buffer.writeBytes(in);
buffer = expandCumulation(alloc, cumulation, in.readableBytes()); } else {
buffer.writeBytes(in); CompositeByteBuf composite;
if (cumulation instanceof CompositeByteBuf) {
composite = (CompositeByteBuf) cumulation;
} else { } else {
CompositeByteBuf composite; composite = alloc.compositeBuffer(Integer.MAX_VALUE);
if (cumulation instanceof CompositeByteBuf) { composite.addComponent(true, cumulation);
composite = (CompositeByteBuf) cumulation;
} else {
composite = alloc.compositeBuffer(Integer.MAX_VALUE);
composite.addComponent(true, cumulation);
}
composite.addComponent(true, in);
in = null;
buffer = composite;
}
return buffer;
} finally {
if (in != null) {
// We must release if the ownership was not transferred as otherwise it may produce a leak if
// writeBytes(...) throw for whatever release (for example because of OutOfMemoryError).
in.release();
} }
composite.addComponent(true, in);
in = null;
buffer = composite;
}
return buffer;
} finally {
if (in != null) {
// We must release if the ownership was not transferred as otherwise it may produce a leak if
// writeBytes(...) throw for whatever release (for example because of OutOfMemoryError).
in.release();
} }
} }
}; };

View File

@ -28,11 +28,8 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
*/ */
final class CodecOutputList extends AbstractList<Object> implements RandomAccess { final class CodecOutputList extends AbstractList<Object> implements RandomAccess {
private static final CodecOutputListRecycler NOOP_RECYCLER = new CodecOutputListRecycler() { private static final CodecOutputListRecycler NOOP_RECYCLER = object -> {
@Override // drop on the floor and let the GC handle it.
public void recycle(CodecOutputList object) {
// drop on the floor and let the GC handle it.
}
}; };
private static final FastThreadLocal<CodecOutputLists> CODEC_OUTPUT_LISTS_POOL = private static final FastThreadLocal<CodecOutputLists> CODEC_OUTPUT_LISTS_POOL =

View File

@ -64,12 +64,7 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
void validateName(K name); void validateName(K name);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
NameValidator NOT_NULL = new NameValidator() { NameValidator NOT_NULL = name -> checkNotNull(name, "name");
@Override
public void validateName(Object name) {
checkNotNull(name, "name");
}
};
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -210,12 +210,9 @@ public abstract class MessageAggregator<I, S, C extends ByteBufHolder, O extends
// Cache the write listener for reuse. // Cache the write listener for reuse.
ChannelFutureListener listener = continueResponseWriteListener; ChannelFutureListener listener = continueResponseWriteListener;
if (listener == null) { if (listener == null) {
continueResponseWriteListener = listener = new ChannelFutureListener() { continueResponseWriteListener = listener = future -> {
@Override if (!future.isSuccess()) {
public void operationComplete(ChannelFuture future) throws Exception { ctx.fireExceptionCaught(future.cause());
if (!future.isSuccess()) {
ctx.fireExceptionCaught(future.cause());
}
} }
}; };
} }

View File

@ -42,12 +42,9 @@ abstract class ByteBufChecksum implements Checksum {
CRC32_UPDATE_METHOD = updateByteBuffer(new CRC32()); CRC32_UPDATE_METHOD = updateByteBuffer(new CRC32());
} }
private final ByteProcessor updateProcessor = new ByteProcessor() { private final ByteProcessor updateProcessor = value -> {
@Override update(value);
public boolean process(byte value) throws Exception { return true;
update(value);
return true;
}
}; };
private static Method updateByteBuffer(Checksum checksum) { private static Method updateByteBuffer(Checksum checksum) {

View File

@ -33,12 +33,7 @@ import static io.netty.handler.codec.compression.Bzip2Constants.*;
* 7. Huffman encode and write data - {@link #close(ByteBuf)} (through {@link Bzip2HuffmanStageEncoder}) * 7. Huffman encode and write data - {@link #close(ByteBuf)} (through {@link Bzip2HuffmanStageEncoder})
*/ */
final class Bzip2BlockCompressor { final class Bzip2BlockCompressor {
private final ByteProcessor writeProcessor = new ByteProcessor() { private final ByteProcessor writeProcessor = this::write;
@Override
public boolean process(byte value) throws Exception {
return write(value);
}
};
/** /**
* A writer that provides bit-level writes. * A writer that provides bit-level writes.

View File

@ -184,12 +184,9 @@ public class Bzip2Encoder extends MessageToByteEncoder<ByteBuf> {
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
return finishEncode(ctx, promise); return finishEncode(ctx, promise);
} else { } else {
executor.execute(new Runnable() { executor.execute(() -> {
@Override ChannelFuture f = finishEncode(ctx(), promise);
public void run() { f.addListener(new ChannelPromiseNotifier(promise));
ChannelFuture f = finishEncode(ctx(), promise);
f.addListener(new ChannelPromiseNotifier(promise));
}
}); });
return promise; return promise;
} }
@ -198,20 +195,12 @@ public class Bzip2Encoder extends MessageToByteEncoder<ByteBuf> {
@Override @Override
public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception { public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
ChannelFuture f = finishEncode(ctx, ctx.newPromise()); ChannelFuture f = finishEncode(ctx, ctx.newPromise());
f.addListener(new ChannelFutureListener() { f.addListener((ChannelFutureListener) f1 -> ctx.close(promise));
@Override
public void operationComplete(ChannelFuture f) throws Exception {
ctx.close(promise);
}
});
if (!f.isDone()) { if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time. // Ensure the channel is closed even if the write operation completes in time.
ctx.executor().schedule(new Runnable() { ctx.executor().schedule(() -> {
@Override ctx.close(promise);
public void run() {
ctx.close(promise);
}
}, 10, TimeUnit.SECONDS); // FIXME: Magic number }, 10, TimeUnit.SECONDS); // FIXME: Magic number
} }
} }

View File

@ -252,12 +252,9 @@ public class JZlibEncoder extends ZlibEncoder {
return finishEncode(ctx, promise); return finishEncode(ctx, promise);
} else { } else {
final ChannelPromise p = ctx.newPromise(); final ChannelPromise p = ctx.newPromise();
executor.execute(new Runnable() { executor.execute(() -> {
@Override ChannelFuture f = finishEncode(ctx(), p);
public void run() { f.addListener(new ChannelPromiseNotifier(promise));
ChannelFuture f = finishEncode(ctx(), p);
f.addListener(new ChannelPromiseNotifier(promise));
}
}); });
return p; return p;
} }
@ -342,20 +339,12 @@ public class JZlibEncoder extends ZlibEncoder {
final ChannelHandlerContext ctx, final ChannelHandlerContext ctx,
final ChannelPromise promise) { final ChannelPromise promise) {
ChannelFuture f = finishEncode(ctx, ctx.newPromise()); ChannelFuture f = finishEncode(ctx, ctx.newPromise());
f.addListener(new ChannelFutureListener() { f.addListener((ChannelFutureListener) f1 -> ctx.close(promise));
@Override
public void operationComplete(ChannelFuture f) throws Exception {
ctx.close(promise);
}
});
if (!f.isDone()) { if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time. // Ensure the channel is closed even if the write operation completes in time.
ctx.executor().schedule(new Runnable() { ctx.executor().schedule(() -> {
@Override ctx.close(promise);
public void run() {
ctx.close(promise);
}
}, 10, TimeUnit.SECONDS); // FIXME: Magic number }, 10, TimeUnit.SECONDS); // FIXME: Magic number
} }
} }

View File

@ -163,12 +163,9 @@ public class JdkZlibEncoder extends ZlibEncoder {
return finishEncode(ctx, promise); return finishEncode(ctx, promise);
} else { } else {
final ChannelPromise p = ctx.newPromise(); final ChannelPromise p = ctx.newPromise();
executor.execute(new Runnable() { executor.execute(() -> {
@Override ChannelFuture f = finishEncode(ctx(), p);
public void run() { f.addListener(new ChannelPromiseNotifier(promise));
ChannelFuture f = finishEncode(ctx(), p);
f.addListener(new ChannelPromiseNotifier(promise));
}
}); });
return p; return p;
} }
@ -262,20 +259,12 @@ public class JdkZlibEncoder extends ZlibEncoder {
@Override @Override
public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception { public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
ChannelFuture f = finishEncode(ctx, ctx.newPromise()); ChannelFuture f = finishEncode(ctx, ctx.newPromise());
f.addListener(new ChannelFutureListener() { f.addListener((ChannelFutureListener) f1 -> ctx.close(promise));
@Override
public void operationComplete(ChannelFuture f) throws Exception {
ctx.close(promise);
}
});
if (!f.isDone()) { if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time. // Ensure the channel is closed even if the write operation completes in time.
ctx.executor().schedule(new Runnable() { ctx.executor().schedule(() -> {
@Override ctx.close(promise);
public void run() {
ctx.close(promise);
}
}, 10, TimeUnit.SECONDS); // FIXME: Magic number }, 10, TimeUnit.SECONDS); // FIXME: Magic number
} }
} }

View File

@ -364,12 +364,9 @@ public class Lz4FrameEncoder extends MessageToByteEncoder<ByteBuf> {
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
return finishEncode(ctx, promise); return finishEncode(ctx, promise);
} else { } else {
executor.execute(new Runnable() { executor.execute(() -> {
@Override ChannelFuture f = finishEncode(ctx(), promise);
public void run() { f.addListener(new ChannelPromiseNotifier(promise));
ChannelFuture f = finishEncode(ctx(), promise);
f.addListener(new ChannelPromiseNotifier(promise));
}
}); });
return promise; return promise;
} }
@ -378,20 +375,12 @@ public class Lz4FrameEncoder extends MessageToByteEncoder<ByteBuf> {
@Override @Override
public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception { public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
ChannelFuture f = finishEncode(ctx, ctx.newPromise()); ChannelFuture f = finishEncode(ctx, ctx.newPromise());
f.addListener(new ChannelFutureListener() { f.addListener((ChannelFutureListener) f1 -> ctx.close(promise));
@Override
public void operationComplete(ChannelFuture f) throws Exception {
ctx.close(promise);
}
});
if (!f.isDone()) { if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time. // Ensure the channel is closed even if the write operation completes in time.
ctx.executor().schedule(new Runnable() { ctx.executor().schedule(() -> {
@Override ctx.close(promise);
public void run() {
ctx.close(promise);
}
}, 10, TimeUnit.SECONDS); // FIXME: Magic number }, 10, TimeUnit.SECONDS); // FIXME: Magic number
} }
} }

View File

@ -270,24 +270,18 @@ public class Lz4FrameEncoderTest extends AbstractEncoderTest {
clientChannel = bs.connect(serverChannel.localAddress()).syncUninterruptibly().channel(); clientChannel = bs.connect(serverChannel.localAddress()).syncUninterruptibly().channel();
final Channel finalClientChannel = clientChannel; final Channel finalClientChannel = clientChannel;
clientChannel.eventLoop().execute(new Runnable() { clientChannel.eventLoop().execute(() -> {
@Override finalClientChannel.close();
public void run() { final int size = 27;
finalClientChannel.close(); ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(size, size);
final int size = 27; finalClientChannel.writeAndFlush(buf.writerIndex(buf.writerIndex() + size))
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(size, size); .addListener((ChannelFutureListener) future -> {
finalClientChannel.writeAndFlush(buf.writerIndex(buf.writerIndex() + size))
.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
try { try {
writeFailCauseRef.set(future.cause()); writeFailCauseRef.set(future.cause());
} finally { } finally {
latch.countDown(); latch.countDown();
} }
} });
});
}
}); });
latch.await(); latch.await();
Throwable writeFailCause = writeFailCauseRef.get(); Throwable writeFailCause = writeFailCauseRef.get();

View File

@ -29,20 +29,10 @@ public interface BooleanSupplier {
/** /**
* A supplier which always returns {@code false} and never throws. * A supplier which always returns {@code false} and never throws.
*/ */
BooleanSupplier FALSE_SUPPLIER = new BooleanSupplier() { BooleanSupplier FALSE_SUPPLIER = () -> false;
@Override
public boolean get() {
return false;
}
};
/** /**
* A supplier which always returns {@code true} and never throws. * A supplier which always returns {@code true} and never throws.
*/ */
BooleanSupplier TRUE_SUPPLIER = new BooleanSupplier() { BooleanSupplier TRUE_SUPPLIER = () -> true;
@Override
public boolean get() {
return true;
}
};
} }

View File

@ -103,42 +103,22 @@ public interface ByteProcessor {
/** /**
* Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}. * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}.
*/ */
ByteProcessor FIND_CRLF = new ByteProcessor() { ByteProcessor FIND_CRLF = value -> value != CARRIAGE_RETURN && value != LINE_FEED;
@Override
public boolean process(byte value) {
return value != CARRIAGE_RETURN && value != LINE_FEED;
}
};
/** /**
* Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}. * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}.
*/ */
ByteProcessor FIND_NON_CRLF = new ByteProcessor() { ByteProcessor FIND_NON_CRLF = value -> value == CARRIAGE_RETURN || value == LINE_FEED;
@Override
public boolean process(byte value) {
return value == CARRIAGE_RETURN || value == LINE_FEED;
}
};
/** /**
* Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}). * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}).
*/ */
ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() { ByteProcessor FIND_LINEAR_WHITESPACE = value -> value != SPACE && value != HTAB;
@Override
public boolean process(byte value) {
return value != SPACE && value != HTAB;
}
};
/** /**
* Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}). * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}).
*/ */
ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() { ByteProcessor FIND_NON_LINEAR_WHITESPACE = value -> value == SPACE || value == HTAB;
@Override
public boolean process(byte value) {
return value == SPACE || value == HTAB;
}
};
/** /**
* @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer. * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer.

View File

@ -250,59 +250,56 @@ public final class NetUtil {
// As a SecurityManager may prevent reading the somaxconn file we wrap this in a privileged block. // As a SecurityManager may prevent reading the somaxconn file we wrap this in a privileged block.
// //
// See https://github.com/netty/netty/issues/3680 // See https://github.com/netty/netty/issues/3680
SOMAXCONN = AccessController.doPrivileged(new PrivilegedAction<Integer>() { SOMAXCONN = AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
@Override // Determine the default somaxconn (server socket backlog) value of the platform.
public Integer run() { // The known defaults:
// Determine the default somaxconn (server socket backlog) value of the platform. // - Windows NT Server 4.0+: 200
// The known defaults: // - Linux and Mac OS X: 128
// - Windows NT Server 4.0+: 200 int somaxconn = PlatformDependent.isWindows() ? 200 : 128;
// - Linux and Mac OS X: 128 File file = new File("/proc/sys/net/core/somaxconn");
int somaxconn = PlatformDependent.isWindows() ? 200 : 128; BufferedReader in = null;
File file = new File("/proc/sys/net/core/somaxconn"); try {
BufferedReader in = null; // file.exists() may throw a SecurityException if a SecurityManager is used, so execute it in the
try { // try / catch block.
// file.exists() may throw a SecurityException if a SecurityManager is used, so execute it in the // See https://github.com/netty/netty/issues/4936
// try / catch block. if (file.exists()) {
// See https://github.com/netty/netty/issues/4936 in = new BufferedReader(new FileReader(file));
if (file.exists()) { somaxconn = Integer.parseInt(in.readLine());
in = new BufferedReader(new FileReader(file)); if (logger.isDebugEnabled()) {
somaxconn = Integer.parseInt(in.readLine()); logger.debug("{}: {}", file, somaxconn);
if (logger.isDebugEnabled()) { }
logger.debug("{}: {}", file, somaxconn); } else {
} // Try to get from sysctl
} else { Integer tmp = null;
// Try to get from sysctl if (SystemPropertyUtil.getBoolean("io.netty.net.somaxconn.trySysctl", false)) {
Integer tmp = null; tmp = sysctlGetInt("kern.ipc.somaxconn");
if (SystemPropertyUtil.getBoolean("io.netty.net.somaxconn.trySysctl", false)) { if (tmp == null) {
tmp = sysctlGetInt("kern.ipc.somaxconn"); tmp = sysctlGetInt("kern.ipc.soacceptqueue");
if (tmp == null) { if (tmp != null) {
tmp = sysctlGetInt("kern.ipc.soacceptqueue");
if (tmp != null) {
somaxconn = tmp;
}
} else {
somaxconn = tmp; somaxconn = tmp;
} }
} } else {
somaxconn = tmp;
if (tmp == null) {
logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file,
somaxconn);
} }
} }
} catch (Exception e) {
logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file, somaxconn, e); if (tmp == null) {
} finally { logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file,
if (in != null) { somaxconn);
try { }
in.close(); }
} catch (Exception e) { } catch (Exception e) {
// Ignored. logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file, somaxconn, e);
} } finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
// Ignored.
} }
} }
return somaxconn;
} }
return somaxconn;
}); });
} }

View File

@ -41,11 +41,8 @@ public abstract class Recycler<T> {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Recycler.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(Recycler.class);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static final Handle NOOP_HANDLE = new Handle() { private static final Handle NOOP_HANDLE = object -> {
@Override // NOOP
public void recycle(Object object) {
// NOOP
}
}; };
private static final AtomicInteger ID_GENERATOR = new AtomicInteger(Integer.MIN_VALUE); private static final AtomicInteger ID_GENERATOR = new AtomicInteger(Integer.MIN_VALUE);
private static final int OWN_THREAD_ID = ID_GENERATOR.getAndIncrement(); private static final int OWN_THREAD_ID = ID_GENERATOR.getAndIncrement();

View File

@ -103,12 +103,8 @@ public abstract class ResourceLeakDetectorFactory {
DefaultResourceLeakDetectorFactory() { DefaultResourceLeakDetectorFactory() {
String customLeakDetector; String customLeakDetector;
try { try {
customLeakDetector = AccessController.doPrivileged(new PrivilegedAction<String>() { customLeakDetector = AccessController.doPrivileged((PrivilegedAction<String>) () ->
@Override SystemPropertyUtil.get("io.netty.customResourceLeakDetector"));
public String run() {
return SystemPropertyUtil.get("io.netty.customResourceLeakDetector");
}
});
} catch (Throwable cause) { } catch (Throwable cause) {
logger.error("Could not access System property: io.netty.customResourceLeakDetector", cause); logger.error("Could not access System property: io.netty.customResourceLeakDetector", cause);
customLeakDetector = null; customLeakDetector = null;

View File

@ -114,12 +114,9 @@ public final class ThreadDeathWatcher {
// See: // See:
// - https://github.com/netty/netty/issues/7290 // - https://github.com/netty/netty/issues/7290
// - https://bugs.openjdk.java.net/browse/JDK-7008595 // - https://bugs.openjdk.java.net/browse/JDK-7008595
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
@Override watcherThread.setContextClassLoader(null);
public Void run() { return null;
watcherThread.setContextClassLoader(null);
return null;
}
}); });
watcherThread.start(); watcherThread.start();

View File

@ -29,20 +29,10 @@ public interface UncheckedBooleanSupplier extends BooleanSupplier {
/** /**
* A supplier which always returns {@code false} and never throws. * A supplier which always returns {@code false} and never throws.
*/ */
UncheckedBooleanSupplier FALSE_SUPPLIER = new UncheckedBooleanSupplier() { UncheckedBooleanSupplier FALSE_SUPPLIER = () -> false;
@Override
public boolean get() {
return false;
}
};
/** /**
* A supplier which always returns {@code true} and never throws. * A supplier which always returns {@code true} and never throws.
*/ */
UncheckedBooleanSupplier TRUE_SUPPLIER = new UncheckedBooleanSupplier() { UncheckedBooleanSupplier TRUE_SUPPLIER = () -> true;
@Override
public boolean get() {
return true;
}
};
} }

View File

@ -36,12 +36,7 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut
static final long START_TIME = System.nanoTime(); static final long START_TIME = System.nanoTime();
private static final Comparator<RunnableScheduledFutureNode<?>> SCHEDULED_FUTURE_TASK_COMPARATOR = private static final Comparator<RunnableScheduledFutureNode<?>> SCHEDULED_FUTURE_TASK_COMPARATOR =
new Comparator<RunnableScheduledFutureNode<?>>() { Comparable::compareTo;
@Override
public int compare(RunnableScheduledFutureNode<?> o1, RunnableScheduledFutureNode<?> o2) {
return o1.compareTo(o2);
}
};
private PriorityQueue<RunnableScheduledFutureNode<?>> scheduledTaskQueue; private PriorityQueue<RunnableScheduledFutureNode<?>> scheduledTaskQueue;
@ -234,12 +229,7 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut
if (inEventLoop()) { if (inEventLoop()) {
add0(task); add0(task);
} else { } else {
execute(new Runnable() { execute(() -> add0(task));
@Override
public void run() {
add0(task);
}
});
} }
return task; return task;
} }
@ -258,12 +248,7 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut
if (inEventLoop()) { if (inEventLoop()) {
scheduledTaskQueue().removeTyped(task); scheduledTaskQueue().removeTyped(task);
} else { } else {
execute(new Runnable() { execute(() -> removeScheduled(task));
@Override
public void run() {
removeScheduled(task);
}
});
} }
} }

View File

@ -429,12 +429,7 @@ public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
} }
} }
safeExecute(executor, new Runnable() { safeExecute(executor, this::notifyListenersNow);
@Override
public void run() {
notifyListenersNow();
}
});
} }
/** /**
@ -459,12 +454,7 @@ public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
} }
} }
safeExecute(executor, new Runnable() { safeExecute(executor, () -> notifyListener0(future, listener));
@Override
public void run() {
notifyListener0(future, listener);
}
});
} }
private void notifyListenersNow() { private void notifyListenersNow() {
@ -662,21 +652,11 @@ public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
if (listeners instanceof GenericProgressiveFutureListener[]) { if (listeners instanceof GenericProgressiveFutureListener[]) {
final GenericProgressiveFutureListener<?>[] array = final GenericProgressiveFutureListener<?>[] array =
(GenericProgressiveFutureListener<?>[]) listeners; (GenericProgressiveFutureListener<?>[]) listeners;
safeExecute(executor, new Runnable() { safeExecute(executor, () -> notifyProgressiveListeners0(self, array, progress, total));
@Override
public void run() {
notifyProgressiveListeners0(self, array, progress, total);
}
});
} else { } else {
final GenericProgressiveFutureListener<ProgressiveFuture<V>> l = final GenericProgressiveFutureListener<ProgressiveFuture<V>> l =
(GenericProgressiveFutureListener<ProgressiveFuture<V>>) listeners; (GenericProgressiveFutureListener<ProgressiveFuture<V>>) listeners;
safeExecute(executor, new Runnable() { safeExecute(executor, () -> notifyProgressiveListener0(self, l, progress, total));
@Override
public void run() {
notifyProgressiveListener0(self, l, progress, total);
}
});
} }
} }
} }

View File

@ -46,12 +46,9 @@ public final class GlobalEventExecutor extends AbstractScheduledEventExecutor {
static { static {
INSTANCE = new GlobalEventExecutor(); INSTANCE = new GlobalEventExecutor();
QUIET_PERIOD_TASK = new RunnableScheduledFutureAdapter<>( QUIET_PERIOD_TASK = new RunnableScheduledFutureAdapter<>(
INSTANCE, INSTANCE.newPromise(), Executors.callable(new Runnable() { INSTANCE, INSTANCE.newPromise(), Executors.callable(() -> {
@Override // NOOP
public void run() { }, null), deadlineNanos(SCHEDULE_QUIET_PERIOD_INTERVAL), -SCHEDULE_QUIET_PERIOD_INTERVAL);
// NOOP
}
}, null), deadlineNanos(SCHEDULE_QUIET_PERIOD_INTERVAL), -SCHEDULE_QUIET_PERIOD_INTERVAL);
INSTANCE.scheduledTaskQueue().add(QUIET_PERIOD_TASK); INSTANCE.scheduledTaskQueue().add(QUIET_PERIOD_TASK);
} }
@ -228,12 +225,9 @@ public final class GlobalEventExecutor extends AbstractScheduledEventExecutor {
// See: // See:
// - https://github.com/netty/netty/issues/7290 // - https://github.com/netty/netty/issues/7290
// - https://bugs.openjdk.java.net/browse/JDK-7008595 // - https://bugs.openjdk.java.net/browse/JDK-7008595
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
@Override t.setContextClassLoader(null);
public Void run() { return null;
t.setContextClassLoader(null);
return null;
}
}); });
// Set the thread before starting it as otherwise inEventLoop() may return false and so produce // Set the thread before starting it as otherwise inEventLoop() may return false and so produce

View File

@ -154,12 +154,9 @@ public class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
} }
} }
final FutureListener<Object> terminationListener = new FutureListener<Object>() { final FutureListener<Object> terminationListener = future -> {
@Override if (terminatedChildren.incrementAndGet() == children.length) {
public void operationComplete(Future<Object> future) throws Exception { terminationFuture.setSuccess(null);
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
} }
}; };

View File

@ -25,11 +25,8 @@ import java.util.concurrent.locks.LockSupport;
* Expose helper methods which create different {@link RejectedExecutionHandler}s. * Expose helper methods which create different {@link RejectedExecutionHandler}s.
*/ */
public final class RejectedExecutionHandlers { public final class RejectedExecutionHandlers {
private static final RejectedExecutionHandler REJECT = new RejectedExecutionHandler() { private static final RejectedExecutionHandler REJECT = (task, executor) -> {
@Override throw new RejectedExecutionException();
public void rejected(Runnable task, SingleThreadEventExecutor executor) {
throw new RejectedExecutionException();
}
}; };
private RejectedExecutionHandlers() { } private RejectedExecutionHandlers() { }
@ -49,24 +46,21 @@ public final class RejectedExecutionHandlers {
public static RejectedExecutionHandler backoff(final int retries, long backoffAmount, TimeUnit unit) { public static RejectedExecutionHandler backoff(final int retries, long backoffAmount, TimeUnit unit) {
ObjectUtil.checkPositive(retries, "retries"); ObjectUtil.checkPositive(retries, "retries");
final long backOffNanos = unit.toNanos(backoffAmount); final long backOffNanos = unit.toNanos(backoffAmount);
return new RejectedExecutionHandler() { return (task, executor) -> {
@Override if (!executor.inEventLoop()) {
public void rejected(Runnable task, SingleThreadEventExecutor executor) { for (int i = 0; i < retries; i++) {
if (!executor.inEventLoop()) { // Try to wake up the executor so it will empty its task queue.
for (int i = 0; i < retries; i++) { executor.wakeup(false);
// Try to wake up the executor so it will empty its task queue.
executor.wakeup(false);
LockSupport.parkNanos(backOffNanos); LockSupport.parkNanos(backOffNanos);
if (executor.offerTask(task)) { if (executor.offerTask(task)) {
return; return;
}
} }
} }
// Either we tried to add the task from within the EventLoop or we was not able to add it even with
// backoff.
throw new RejectedExecutionException();
} }
// Either we tried to add the task from within the EventLoop or we was not able to add it even with
// backoff.
throw new RejectedExecutionException();
}; };
} }
} }

View File

@ -59,17 +59,11 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im
private static final int ST_SHUTDOWN = 4; private static final int ST_SHUTDOWN = 4;
private static final int ST_TERMINATED = 5; private static final int ST_TERMINATED = 5;
private static final Runnable WAKEUP_TASK = new Runnable() { private static final Runnable WAKEUP_TASK = () -> {
@Override // Do nothing.
public void run() {
// Do nothing.
}
}; };
private static final Runnable NOOP_TASK = new Runnable() { private static final Runnable NOOP_TASK = () -> {
@Override // Do nothing.
public void run() {
// Do nothing.
}
}; };
private static final AtomicIntegerFieldUpdater<SingleThreadEventExecutor> STATE_UPDATER = private static final AtomicIntegerFieldUpdater<SingleThreadEventExecutor> STATE_UPDATER =
@ -467,12 +461,7 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im
if (inEventLoop()) { if (inEventLoop()) {
shutdownHooks.add(task); shutdownHooks.add(task);
} else { } else {
execute(new Runnable() { execute(() -> shutdownHooks.add(task));
@Override
public void run() {
shutdownHooks.add(task);
}
});
} }
} }
@ -483,12 +472,7 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im
if (inEventLoop()) { if (inEventLoop()) {
shutdownHooks.remove(task); shutdownHooks.remove(task);
} else { } else {
execute(new Runnable() { execute(() -> shutdownHooks.remove(task));
@Override
public void run() {
shutdownHooks.remove(task);
}
});
} }
} }
@ -854,66 +838,63 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im
private void doStartThread() { private void doStartThread() {
assert thread == null; assert thread == null;
executor.execute(new Runnable() { executor.execute(() -> {
@Override thread = Thread.currentThread();
public void run() { if (interrupted) {
thread = Thread.currentThread(); thread.interrupt();
if (interrupted) { }
thread.interrupt();
boolean success = false;
updateLastExecutionTime();
try {
SingleThreadEventExecutor.this.run();
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
for (;;) {
int oldState = state;
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break;
}
}
// Check if confirmShutdown() was called at the end of the loop.
if (success && gracefulShutdownStartTime == 0) {
if (logger.isErrorEnabled()) {
logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
"be called before run() implementation terminates.");
}
} }
boolean success = false;
updateLastExecutionTime();
try { try {
SingleThreadEventExecutor.this.run(); // Run all remaining tasks and shutdown hooks.
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
for (;;) { for (;;) {
int oldState = state; if (confirmShutdown()) {
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break; break;
} }
} }
} finally {
// Check if confirmShutdown() was called at the end of the loop.
if (success && gracefulShutdownStartTime == 0) {
if (logger.isErrorEnabled()) {
logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
"be called before run() implementation terminates.");
}
}
try { try {
// Run all remaining tasks and shutdown hooks. cleanup();
for (;;) {
if (confirmShutdown()) {
break;
}
}
} finally { } finally {
try { // Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
cleanup(); // the future. The user may block on the future and once it unblocks the JVM may terminate
} finally { // and start unloading classes.
// Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify // See https://github.com/netty/netty/issues/6596.
// the future. The user may block on the future and once it unblocks the JVM may terminate FastThreadLocal.removeAll();
// and start unloading classes.
// See https://github.com/netty/netty/issues/6596.
FastThreadLocal.removeAll();
STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED); STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
threadLock.release(); threadLock.release();
if (!taskQueue.isEmpty()) { if (!taskQueue.isEmpty()) {
if (logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
logger.warn("An event executor terminated with " + logger.warn("An event executor terminated with " +
"non-empty task queue (" + taskQueue.size() + ')'); "non-empty task queue (" + taskQueue.size() + ')');
}
} }
terminationFuture.setSuccess(null);
} }
terminationFuture.setSuccess(null);
} }
} }
} }

View File

@ -45,20 +45,17 @@ final class CleanerJava6 implements Cleaner {
Throwable error = null; Throwable error = null;
final ByteBuffer direct = ByteBuffer.allocateDirect(1); final ByteBuffer direct = ByteBuffer.allocateDirect(1);
try { try {
Object mayBeCleanerField = AccessController.doPrivileged(new PrivilegedAction<Object>() { Object mayBeCleanerField = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { Field cleanerField1 = direct.getClass().getDeclaredField("cleaner");
try { if (!PlatformDependent.hasUnsafe()) {
Field cleanerField = direct.getClass().getDeclaredField("cleaner"); // We need to make it accessible if we do not use Unsafe as we will access it via
if (!PlatformDependent.hasUnsafe()) { // reflection.
// We need to make it accessible if we do not use Unsafe as we will access it via cleanerField1.setAccessible(true);
// reflection.
cleanerField.setAccessible(true);
}
return cleanerField;
} catch (Throwable cause) {
return cause;
} }
return cleanerField1;
} catch (Throwable cause) {
return cause;
} }
}); });
if (mayBeCleanerField instanceof Throwable) { if (mayBeCleanerField instanceof Throwable) {
@ -119,15 +116,12 @@ final class CleanerJava6 implements Cleaner {
} }
private static void freeDirectBufferPrivileged(final ByteBuffer buffer) { private static void freeDirectBufferPrivileged(final ByteBuffer buffer) {
Throwable cause = AccessController.doPrivileged(new PrivilegedAction<Throwable>() { Throwable cause = AccessController.doPrivileged((PrivilegedAction<Throwable>) () -> {
@Override try {
public Throwable run() { freeDirectBuffer0(buffer);
try { return null;
freeDirectBuffer0(buffer); } catch (Throwable cause1) {
return null; return cause1;
} catch (Throwable cause) {
return cause;
}
} }
}); });
if (cause != null) { if (cause != null) {

View File

@ -37,18 +37,15 @@ final class CleanerJava9 implements Cleaner {
final Throwable error; final Throwable error;
if (PlatformDependent0.hasUnsafe()) { if (PlatformDependent0.hasUnsafe()) {
final ByteBuffer buffer = ByteBuffer.allocateDirect(1); final ByteBuffer buffer = ByteBuffer.allocateDirect(1);
Object maybeInvokeMethod = AccessController.doPrivileged(new PrivilegedAction<Object>() { Object maybeInvokeMethod = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { // See https://bugs.openjdk.java.net/browse/JDK-8171377
try { Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod(
// See https://bugs.openjdk.java.net/browse/JDK-8171377 "invokeCleaner", ByteBuffer.class);
Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod( m.invoke(PlatformDependent0.UNSAFE, buffer);
"invokeCleaner", ByteBuffer.class); return m;
m.invoke(PlatformDependent0.UNSAFE, buffer); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
return m; return e;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
return e;
}
} }
}); });
@ -91,16 +88,13 @@ final class CleanerJava9 implements Cleaner {
} }
private static void freeDirectBufferPrivileged(final ByteBuffer buffer) { private static void freeDirectBufferPrivileged(final ByteBuffer buffer) {
Exception error = AccessController.doPrivileged(new PrivilegedAction<Exception>() { Exception error = AccessController.doPrivileged((PrivilegedAction<Exception>) () -> {
@Override try {
public Exception run() { INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer);
try { } catch (InvocationTargetException | IllegalAccessException e) {
INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer); return e;
} catch (InvocationTargetException | IllegalAccessException e) {
return e;
}
return null;
} }
return null;
}); });
if (error != null) { if (error != null) {
PlatformDependent0.throwException(error); PlatformDependent0.throwException(error);

View File

@ -322,18 +322,15 @@ public final class NativeLibraryLoader {
private static void loadLibraryByHelper(final Class<?> helper, final String name, final boolean absolute) private static void loadLibraryByHelper(final Class<?> helper, final String name, final boolean absolute)
throws UnsatisfiedLinkError { throws UnsatisfiedLinkError {
Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() { Object ret = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { // Invoke the helper to load the native library, if succeed, then the native
try { // library belong to the specified ClassLoader.
// Invoke the helper to load the native library, if succeed, then the native Method method = helper.getMethod("loadLibrary", String.class, boolean.class);
// library belong to the specified ClassLoader. method.setAccessible(true);
Method method = helper.getMethod("loadLibrary", String.class, boolean.class); return method.invoke(null, name, absolute);
method.setAccessible(true); } catch (Exception e) {
return method.invoke(null, name, absolute); return e;
} catch (Exception e) {
return e;
}
} }
}); });
if (ret instanceof Throwable) { if (ret instanceof Throwable) {
@ -368,20 +365,17 @@ public final class NativeLibraryLoader {
try { try {
// The helper class is NOT found in target ClassLoader, we have to define the helper class. // The helper class is NOT found in target ClassLoader, we have to define the helper class.
final byte[] classBinary = classToByteArray(helper); final byte[] classBinary = classToByteArray(helper);
return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { return AccessController.doPrivileged((PrivilegedAction<Class<?>>) () -> {
@Override try {
public Class<?> run() { // Define the helper class in the target ClassLoader,
try { // then we can call the helper to load the native library.
// Define the helper class in the target ClassLoader, Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class,
// then we can call the helper to load the native library. byte[].class, int.class, int.class);
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, defineClass.setAccessible(true);
byte[].class, int.class, int.class); return (Class<?>) defineClass.invoke(loader, helper.getName(), classBinary, 0,
defineClass.setAccessible(true); classBinary.length);
return (Class<?>) defineClass.invoke(loader, helper.getName(), classBinary, 0, } catch (Exception e) {
classBinary.length); throw new IllegalStateException("Define class failed!", e);
} catch (Exception e) {
throw new IllegalStateException("Define class failed!", e);
}
} }
}); });
} catch (ClassNotFoundException | Error | RuntimeException e2) { } catch (ClassNotFoundException | Error | RuntimeException e2) {

View File

@ -42,47 +42,44 @@ public final class ObjectCleaner {
private static final Set<AutomaticCleanerReference> LIVE_SET = ConcurrentHashMap.newKeySet(); private static final Set<AutomaticCleanerReference> LIVE_SET = ConcurrentHashMap.newKeySet();
private static final ReferenceQueue<Object> REFERENCE_QUEUE = new ReferenceQueue<>(); private static final ReferenceQueue<Object> REFERENCE_QUEUE = new ReferenceQueue<>();
private static final AtomicBoolean CLEANER_RUNNING = new AtomicBoolean(false); private static final AtomicBoolean CLEANER_RUNNING = new AtomicBoolean(false);
private static final Runnable CLEANER_TASK = new Runnable() { private static final Runnable CLEANER_TASK = () -> {
@Override boolean interrupted = false;
public void run() { for (;;) {
boolean interrupted = false; // Keep on processing as long as the LIVE_SET is not empty and once it becomes empty
for (;;) { // See if we can let this thread complete.
// Keep on processing as long as the LIVE_SET is not empty and once it becomes empty while (!LIVE_SET.isEmpty()) {
// See if we can let this thread complete. final AutomaticCleanerReference reference;
while (!LIVE_SET.isEmpty()) { try {
final AutomaticCleanerReference reference; reference = (AutomaticCleanerReference) REFERENCE_QUEUE.remove(REFERENCE_QUEUE_POLL_TIMEOUT_MS);
} catch (InterruptedException ex) {
// Just consume and move on
interrupted = true;
continue;
}
if (reference != null) {
try { try {
reference = (AutomaticCleanerReference) REFERENCE_QUEUE.remove(REFERENCE_QUEUE_POLL_TIMEOUT_MS); reference.cleanup();
} catch (InterruptedException ex) { } catch (Throwable ignored) {
// Just consume and move on // ignore exceptions, and don't log in case the logger throws an exception, blocks, or has
interrupted = true; // other unexpected side effects.
continue;
}
if (reference != null) {
try {
reference.cleanup();
} catch (Throwable ignored) {
// ignore exceptions, and don't log in case the logger throws an exception, blocks, or has
// other unexpected side effects.
}
LIVE_SET.remove(reference);
} }
LIVE_SET.remove(reference);
} }
CLEANER_RUNNING.set(false); }
CLEANER_RUNNING.set(false);
// Its important to first access the LIVE_SET and then CLEANER_RUNNING to ensure correct // Its important to first access the LIVE_SET and then CLEANER_RUNNING to ensure correct
// behavior in multi-threaded environments. // behavior in multi-threaded environments.
if (LIVE_SET.isEmpty() || !CLEANER_RUNNING.compareAndSet(false, true)) { if (LIVE_SET.isEmpty() || !CLEANER_RUNNING.compareAndSet(false, true)) {
// There was nothing added after we set STARTED to false or some other cleanup Thread // There was nothing added after we set STARTED to false or some other cleanup Thread
// was started already so its safe to let this Thread complete now. // was started already so its safe to let this Thread complete now.
break; break;
}
}
if (interrupted) {
// As we caught the InterruptedException above we should mark the Thread as interrupted.
Thread.currentThread().interrupt();
} }
} }
if (interrupted) {
// As we caught the InterruptedException above we should mark the Thread as interrupted.
Thread.currentThread().interrupt();
}
}; };
/** /**
@ -108,12 +105,9 @@ public final class ObjectCleaner {
// See: // See:
// - https://github.com/netty/netty/issues/7290 // - https://github.com/netty/netty/issues/7290
// - https://bugs.openjdk.java.net/browse/JDK-7008595 // - https://bugs.openjdk.java.net/browse/JDK-7008595
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
@Override cleanupThread.setContextClassLoader(null);
public Void run() { return null;
cleanupThread.setContextClassLoader(null);
return null;
}
}); });
cleanupThread.setName(CLEANER_THREAD_NAME); cleanupThread.setName(CLEANER_THREAD_NAME);

View File

@ -99,11 +99,8 @@ public final class PlatformDependent {
public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
private static final Cleaner NOOP = new Cleaner() { private static final Cleaner NOOP = buffer -> {
@Override // NOOP
public void freeDirectBuffer(ByteBuffer buffer) {
// NOOP
}
}; };
static { static {
@ -775,12 +772,9 @@ public final class PlatformDependent {
// jctools goes through its own process of initializing unsafe; of // jctools goes through its own process of initializing unsafe; of
// course, this requires permissions which might not be granted to calling code, so we // course, this requires permissions which might not be granted to calling code, so we
// must mark this block as privileged too // must mark this block as privileged too
unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() { unsafe = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override // force JCTools to initialize unsafe
public Object run() { return UnsafeAccess.UNSAFE;
// force JCTools to initialize unsafe
return UnsafeAccess.UNSAFE;
}
}); });
} }

View File

@ -80,25 +80,22 @@ final class PlatformDependent0 {
direct = ByteBuffer.allocateDirect(1); direct = ByteBuffer.allocateDirect(1);
// attempt to access field Unsafe#theUnsafe // attempt to access field Unsafe#theUnsafe
final Object maybeUnsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() { final Object maybeUnsafe = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
try { // We always want to try using Unsafe as the access still works on java9 as well and
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); // we need it for out native-transports and many optimizations.
// We always want to try using Unsafe as the access still works on java9 as well and Throwable cause = ReflectionUtil.trySetAccessible(unsafeField, false);
// we need it for out native-transports and many optimizations. if (cause != null) {
Throwable cause = ReflectionUtil.trySetAccessible(unsafeField, false); return cause;
if (cause != null) { }
return cause; // the unsafe instance
} return unsafeField.get(null);
// the unsafe instance } catch (NoSuchFieldException | SecurityException
return unsafeField.get(null); | IllegalAccessException | NoClassDefFoundError e) {
} catch (NoSuchFieldException | SecurityException return e;
| IllegalAccessException | NoClassDefFoundError e) { } // Also catch NoClassDefFoundError in case someone uses for example OSGI and it made
return e; // Unsafe unloadable.
} // Also catch NoClassDefFoundError in case someone uses for example OSGI and it made
// Unsafe unloadable.
}
}); });
// the conditional check here can not be replaced with checking that maybeUnsafe // the conditional check here can not be replaced with checking that maybeUnsafe
@ -119,16 +116,13 @@ final class PlatformDependent0 {
// http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html
if (unsafe != null) { if (unsafe != null) {
final Unsafe finalUnsafe = unsafe; final Unsafe finalUnsafe = unsafe;
final Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() { final Object maybeException = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { finalUnsafe.getClass().getDeclaredMethod(
try { "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
finalUnsafe.getClass().getDeclaredMethod( return null;
"copyMemory", Object.class, long.class, Object.class, long.class, long.class); } catch (NoSuchMethodException | SecurityException e) {
return null; return e;
} catch (NoSuchMethodException | SecurityException e) {
return e;
}
} }
}); });
@ -146,24 +140,21 @@ final class PlatformDependent0 {
final Unsafe finalUnsafe = unsafe; final Unsafe finalUnsafe = unsafe;
// attempt to access field Buffer#address // attempt to access field Buffer#address
final Object maybeAddressField = AccessController.doPrivileged(new PrivilegedAction<Object>() { final Object maybeAddressField = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { final Field field = Buffer.class.getDeclaredField("address");
try { // Use Unsafe to read value of the address field. This way it will not fail on JDK9+ which
final Field field = Buffer.class.getDeclaredField("address"); // will forbid changing the access level via reflection.
// Use Unsafe to read value of the address field. This way it will not fail on JDK9+ which final long offset = finalUnsafe.objectFieldOffset(field);
// will forbid changing the access level via reflection. final long address = finalUnsafe.getLong(direct, offset);
final long offset = finalUnsafe.objectFieldOffset(field);
final long address = finalUnsafe.getLong(direct, offset);
// if direct really is a direct buffer, address will be non-zero // if direct really is a direct buffer, address will be non-zero
if (address == 0) { if (address == 0) {
return null; return null;
}
return field;
} catch (NoSuchFieldException | SecurityException e) {
return e;
} }
return field;
} catch (NoSuchFieldException | SecurityException e) {
return e;
} }
}); });
@ -205,20 +196,17 @@ final class PlatformDependent0 {
long address = -1; long address = -1;
try { try {
final Object maybeDirectBufferConstructor = final Object maybeDirectBufferConstructor =
AccessController.doPrivileged(new PrivilegedAction<Object>() { AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { final Constructor<?> constructor =
try { direct.getClass().getDeclaredConstructor(long.class, int.class);
final Constructor<?> constructor = Throwable cause = ReflectionUtil.trySetAccessible(constructor, true);
direct.getClass().getDeclaredConstructor(long.class, int.class); if (cause != null) {
Throwable cause = ReflectionUtil.trySetAccessible(constructor, true); return cause;
if (cause != null) {
return cause;
}
return constructor;
} catch (NoSuchMethodException | SecurityException e) {
return e;
} }
return constructor;
} catch (NoSuchMethodException | SecurityException e) {
return e;
} }
}); });
@ -299,33 +287,27 @@ final class PlatformDependent0 {
UNALIGNED = unaligned; UNALIGNED = unaligned;
if (javaVersion() >= 9) { if (javaVersion() >= 9) {
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() { Object maybeException = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { // Java9 has jdk.internal.misc.Unsafe and not all methods are propagated to
try { // sun.misc.Unsafe
// Java9 has jdk.internal.misc.Unsafe and not all methods are propagated to Class<?> internalUnsafeClass = getClassLoader(PlatformDependent0.class)
// sun.misc.Unsafe .loadClass("jdk.internal.misc.Unsafe");
Class<?> internalUnsafeClass = getClassLoader(PlatformDependent0.class) Method method = internalUnsafeClass.getDeclaredMethod("getUnsafe");
.loadClass("jdk.internal.misc.Unsafe"); return method.invoke(null);
Method method = internalUnsafeClass.getDeclaredMethod("getUnsafe"); } catch (Throwable e) {
return method.invoke(null); return e;
} catch (Throwable e) {
return e;
}
} }
}); });
if (!(maybeException instanceof Throwable)) { if (!(maybeException instanceof Throwable)) {
internalUnsafe = maybeException; internalUnsafe = maybeException;
final Object finalInternalUnsafe = internalUnsafe; final Object finalInternalUnsafe = internalUnsafe;
maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() { maybeException = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
@Override try {
public Object run() { return finalInternalUnsafe.getClass().getDeclaredMethod(
try { "allocateUninitializedArray", Class.class, int.class);
return finalInternalUnsafe.getClass().getDeclaredMethod( } catch (NoSuchMethodException | SecurityException e) {
"allocateUninitializedArray", Class.class, int.class); return e;
} catch (NoSuchMethodException | SecurityException e) {
return e;
}
} }
}); });
@ -746,12 +728,7 @@ final class PlatformDependent0 {
if (System.getSecurityManager() == null) { if (System.getSecurityManager() == null) {
return clazz.getClassLoader(); return clazz.getClassLoader();
} else { } else {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) clazz::getClassLoader);
@Override
public ClassLoader run() {
return clazz.getClassLoader();
}
});
} }
} }
@ -759,12 +736,8 @@ final class PlatformDependent0 {
if (System.getSecurityManager() == null) { if (System.getSecurityManager() == null) {
return Thread.currentThread().getContextClassLoader(); return Thread.currentThread().getContextClassLoader();
} else { } else {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () ->
@Override Thread.currentThread().getContextClassLoader());
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
} }
} }
@ -772,12 +745,7 @@ final class PlatformDependent0 {
if (System.getSecurityManager() == null) { if (System.getSecurityManager() == null) {
return ClassLoader.getSystemClassLoader(); return ClassLoader.getSystemClassLoader();
} else { } else {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) ClassLoader::getSystemClassLoader);
@Override
public ClassLoader run() {
return ClassLoader.getSystemClassLoader();
}
});
} }
} }

View File

@ -48,12 +48,9 @@ public final class SocketUtils {
public static void connect(final Socket socket, final SocketAddress remoteAddress, final int timeout) public static void connect(final Socket socket, final SocketAddress remoteAddress, final int timeout)
throws IOException { throws IOException {
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
@Override socket.connect(remoteAddress, timeout);
public Void run() throws IOException { return null;
socket.connect(remoteAddress, timeout);
return null;
}
}); });
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
@ -62,12 +59,9 @@ public final class SocketUtils {
public static void bind(final Socket socket, final SocketAddress bindpoint) throws IOException { public static void bind(final Socket socket, final SocketAddress bindpoint) throws IOException {
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
@Override socket.bind(bindpoint);
public Void run() throws IOException { return null;
socket.bind(bindpoint);
return null;
}
}); });
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
@ -77,12 +71,8 @@ public final class SocketUtils {
public static boolean connect(final SocketChannel socketChannel, final SocketAddress remoteAddress) public static boolean connect(final SocketChannel socketChannel, final SocketAddress remoteAddress)
throws IOException { throws IOException {
try { try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() { return AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () ->
@Override socketChannel.connect(remoteAddress));
public Boolean run() throws IOException {
return socketChannel.connect(remoteAddress);
}
});
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
} }
@ -90,12 +80,9 @@ public final class SocketUtils {
public static void bind(final SocketChannel socketChannel, final SocketAddress address) throws IOException { public static void bind(final SocketChannel socketChannel, final SocketAddress address) throws IOException {
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
@Override socketChannel.bind(address);
public Void run() throws IOException { return null;
socketChannel.bind(address);
return null;
}
}); });
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
@ -104,12 +91,8 @@ public final class SocketUtils {
public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException { public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException {
try { try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<SocketChannel>() { return AccessController.doPrivileged(
@Override (PrivilegedExceptionAction<SocketChannel>) serverSocketChannel::accept);
public SocketChannel run() throws IOException {
return serverSocketChannel.accept();
}
});
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
} }
@ -117,12 +100,9 @@ public final class SocketUtils {
public static void bind(final DatagramChannel networkChannel, final SocketAddress address) throws IOException { public static void bind(final DatagramChannel networkChannel, final SocketAddress address) throws IOException {
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
@Override networkChannel.bind(address);
public Void run() throws IOException { return null;
networkChannel.bind(address);
return null;
}
}); });
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (IOException) e.getCause(); throw (IOException) e.getCause();
@ -130,22 +110,13 @@ public final class SocketUtils {
} }
public static SocketAddress localSocketAddress(final ServerSocket socket) { public static SocketAddress localSocketAddress(final ServerSocket socket) {
return AccessController.doPrivileged(new PrivilegedAction<SocketAddress>() { return AccessController.doPrivileged((PrivilegedAction<SocketAddress>) socket::getLocalSocketAddress);
@Override
public SocketAddress run() {
return socket.getLocalSocketAddress();
}
});
} }
public static InetAddress addressByName(final String hostname) throws UnknownHostException { public static InetAddress addressByName(final String hostname) throws UnknownHostException {
try { try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<InetAddress>() { return AccessController.doPrivileged((PrivilegedExceptionAction<InetAddress>) () ->
@Override InetAddress.getByName(hostname));
public InetAddress run() throws UnknownHostException {
return InetAddress.getByName(hostname);
}
});
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (UnknownHostException) e.getCause(); throw (UnknownHostException) e.getCause();
} }
@ -153,52 +124,29 @@ public final class SocketUtils {
public static InetAddress[] allAddressesByName(final String hostname) throws UnknownHostException { public static InetAddress[] allAddressesByName(final String hostname) throws UnknownHostException {
try { try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<InetAddress[]>() { return AccessController.doPrivileged((PrivilegedExceptionAction<InetAddress[]>) () ->
@Override InetAddress.getAllByName(hostname));
public InetAddress[] run() throws UnknownHostException {
return InetAddress.getAllByName(hostname);
}
});
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (UnknownHostException) e.getCause(); throw (UnknownHostException) e.getCause();
} }
} }
public static InetSocketAddress socketAddress(final String hostname, final int port) { public static InetSocketAddress socketAddress(final String hostname, final int port) {
return AccessController.doPrivileged(new PrivilegedAction<InetSocketAddress>() { return AccessController.doPrivileged((PrivilegedAction<InetSocketAddress>) () ->
@Override new InetSocketAddress(hostname, port));
public InetSocketAddress run() {
return new InetSocketAddress(hostname, port);
}
});
} }
public static Enumeration<InetAddress> addressesFromNetworkInterface(final NetworkInterface intf) { public static Enumeration<InetAddress> addressesFromNetworkInterface(final NetworkInterface intf) {
return AccessController.doPrivileged(new PrivilegedAction<Enumeration<InetAddress>>() { return AccessController.doPrivileged((PrivilegedAction<Enumeration<InetAddress>>) intf::getInetAddresses);
@Override
public Enumeration<InetAddress> run() {
return intf.getInetAddresses();
}
});
} }
public static InetAddress loopbackAddress() { public static InetAddress loopbackAddress() {
return AccessController.doPrivileged(new PrivilegedAction<InetAddress>() { return AccessController.doPrivileged((PrivilegedAction<InetAddress>) InetAddress::getLoopbackAddress);
@Override
public InetAddress run() {
return InetAddress.getLoopbackAddress();
}
});
} }
public static byte[] hardwareAddressFromNetworkInterface(final NetworkInterface intf) throws SocketException { public static byte[] hardwareAddressFromNetworkInterface(final NetworkInterface intf) throws SocketException {
try { try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<byte[]>() { return AccessController.doPrivileged((PrivilegedExceptionAction<byte[]>) intf::getHardwareAddress);
@Override
public byte[] run() throws SocketException {
return intf.getHardwareAddress();
}
});
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
throw (SocketException) e.getCause(); throw (SocketException) e.getCause();
} }

View File

@ -68,12 +68,7 @@ public final class SystemPropertyUtil {
if (System.getSecurityManager() == null) { if (System.getSecurityManager() == null) {
value = System.getProperty(key); value = System.getProperty(key);
} else { } else {
value = AccessController.doPrivileged(new PrivilegedAction<String>() { value = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(key));
@Override
public String run() {
return System.getProperty(key);
}
});
} }
} catch (SecurityException e) { } catch (SecurityException e) {
logger.warn("Unable to retrieve a system property '{}'; default values will be used.", key, e); logger.warn("Unable to retrieve a system property '{}'; default values will be used.", key, e);

View File

@ -35,19 +35,16 @@ class Log4J2Logger extends ExtendedLoggerWrapper implements InternalLogger {
// Older Log4J2 versions have only log methods that takes the format + varargs. So we should not use // Older Log4J2 versions have only log methods that takes the format + varargs. So we should not use
// Log4J2 if the version is too old. // Log4J2 if the version is too old.
// See https://github.com/netty/netty/issues/8217 // See https://github.com/netty/netty/issues/8217
VARARGS_ONLY = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { VARARGS_ONLY = AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
@Override try {
public Boolean run() { Logger.class.getMethod("debug", String.class, Object.class);
try { return false;
Logger.class.getMethod("debug", String.class, Object.class); } catch (NoSuchMethodException ignore) {
return false; // Log4J2 version too old.
} catch (NoSuchMethodException ignore) { return true;
// Log4J2 version too old. } catch (SecurityException ignore) {
return true; // We could not detect the version so we will use Log4J2 if its on the classpath.
} catch (SecurityException ignore) { return false;
// We could not detect the version so we will use Log4J2 if its on the classpath.
return false;
}
} }
}); });
} }

View File

@ -98,19 +98,16 @@ public class AbstractReferenceCountedTest {
for (int a = 0; a < threads; a++) { for (int a = 0; a < threads; a++) {
final int retainCnt = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE); final int retainCnt = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE);
futures.add(service.submit(new Runnable() { futures.add(service.submit(() -> {
@Override try {
public void run() { retainLatch.await();
try { try {
retainLatch.await(); referenceCounted.retain(retainCnt);
try { } catch (IllegalReferenceCountException e) {
referenceCounted.retain(retainCnt); refCountExceptions.incrementAndGet();
} catch (IllegalReferenceCountException e) {
refCountExceptions.incrementAndGet();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} }
})); }));
} }
@ -147,21 +144,18 @@ public class AbstractReferenceCountedTest {
for (int a = 0; a < threads; a++) { for (int a = 0; a < threads; a++) {
final AtomicInteger releaseCnt = new AtomicInteger(0); final AtomicInteger releaseCnt = new AtomicInteger(0);
futures.add(service.submit(new Runnable() { futures.add(service.submit(() -> {
@Override try {
public void run() { releaseLatch.await();
try { try {
releaseLatch.await(); if (referenceCounted.release(releaseCnt.incrementAndGet())) {
try { releasedCount.incrementAndGet();
if (referenceCounted.release(releaseCnt.incrementAndGet())) {
releasedCount.incrementAndGet();
}
} catch (IllegalReferenceCountException e) {
refCountExceptions.incrementAndGet();
} }
} catch (InterruptedException e) { } catch (IllegalReferenceCountException e) {
Thread.currentThread().interrupt(); refCountExceptions.incrementAndGet();
} }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} }
})); }));
} }

View File

@ -79,12 +79,7 @@ public class ConstantPoolTest {
assertThat(array.length, is(5)); assertThat(array.length, is(5));
// Sort by name // Sort by name
Arrays.sort(array, new Comparator<TestConstant>() { Arrays.sort(array, (o1, o2) -> o1.name().compareTo(o2.name()));
@Override
public int compare(TestConstant o1, TestConstant o2) {
return o1.name().compareTo(o2.name());
}
});
assertThat(array[0], is(sameInstance(a))); assertThat(array[0], is(sameInstance(a)));
assertThat(array[1], is(sameInstance(b))); assertThat(array[1], is(sameInstance(b)));

View File

@ -35,12 +35,9 @@ public class HashedWheelTimerTest {
public void testScheduleTimeoutShouldNotRunBeforeDelay() throws InterruptedException { public void testScheduleTimeoutShouldNotRunBeforeDelay() throws InterruptedException {
final Timer timer = new HashedWheelTimer(); final Timer timer = new HashedWheelTimer();
final CountDownLatch barrier = new CountDownLatch(1); final CountDownLatch barrier = new CountDownLatch(1);
final Timeout timeout = timer.newTimeout(new TimerTask() { final Timeout timeout = timer.newTimeout(timeout1 -> {
@Override fail("This should not have run");
public void run(Timeout timeout) throws Exception { barrier.countDown();
fail("This should not have run");
barrier.countDown();
}
}, 10, TimeUnit.SECONDS); }, 10, TimeUnit.SECONDS);
assertFalse(barrier.await(3, TimeUnit.SECONDS)); assertFalse(barrier.await(3, TimeUnit.SECONDS));
assertFalse("timer should not expire", timeout.isExpired()); assertFalse("timer should not expire", timeout.isExpired());
@ -51,12 +48,7 @@ public class HashedWheelTimerTest {
public void testScheduleTimeoutShouldRunAfterDelay() throws InterruptedException { public void testScheduleTimeoutShouldRunAfterDelay() throws InterruptedException {
final Timer timer = new HashedWheelTimer(); final Timer timer = new HashedWheelTimer();
final CountDownLatch barrier = new CountDownLatch(1); final CountDownLatch barrier = new CountDownLatch(1);
final Timeout timeout = timer.newTimeout(new TimerTask() { final Timeout timeout = timer.newTimeout(timeout1 -> barrier.countDown(), 2, TimeUnit.SECONDS);
@Override
public void run(Timeout timeout) throws Exception {
barrier.countDown();
}
}, 2, TimeUnit.SECONDS);
assertTrue(barrier.await(3, TimeUnit.SECONDS)); assertTrue(barrier.await(3, TimeUnit.SECONDS));
assertTrue("timer should expire", timeout.isExpired()); assertTrue("timer should expire", timeout.isExpired());
timer.stop(); timer.stop();
@ -67,12 +59,7 @@ public class HashedWheelTimerTest {
final CountDownLatch latch = new CountDownLatch(3); final CountDownLatch latch = new CountDownLatch(3);
final Timer timerProcessed = new HashedWheelTimer(); final Timer timerProcessed = new HashedWheelTimer();
for (int i = 0; i < 3; i ++) { for (int i = 0; i < 3; i ++) {
timerProcessed.newTimeout(new TimerTask() { timerProcessed.newTimeout(timeout -> latch.countDown(), 1, TimeUnit.MILLISECONDS);
@Override
public void run(final Timeout timeout) throws Exception {
latch.countDown();
}
}, 1, TimeUnit.MILLISECONDS);
} }
latch.await(); latch.await();
@ -80,10 +67,7 @@ public class HashedWheelTimerTest {
final Timer timerUnprocessed = new HashedWheelTimer(); final Timer timerUnprocessed = new HashedWheelTimer();
for (int i = 0; i < 5; i ++) { for (int i = 0; i < 5; i ++) {
timerUnprocessed.newTimeout(new TimerTask() { timerUnprocessed.newTimeout(timeout -> {
@Override
public void run(Timeout timeout) throws Exception {
}
}, 5, TimeUnit.SECONDS); }, 5, TimeUnit.SECONDS);
} }
Thread.sleep(1000L); // sleep for a second Thread.sleep(1000L); // sleep for a second
@ -95,12 +79,7 @@ public class HashedWheelTimerTest {
final CountDownLatch latch = new CountDownLatch(3); final CountDownLatch latch = new CountDownLatch(3);
final Timer timer = new HashedWheelTimer(); final Timer timer = new HashedWheelTimer();
for (int i = 0; i < 3; i ++) { for (int i = 0; i < 3; i ++) {
timer.newTimeout(new TimerTask() { timer.newTimeout(timeout -> latch.countDown(), 1, TimeUnit.MILLISECONDS);
@Override
public void run(Timeout timeout) throws Exception {
latch.countDown();
}
}, 1, TimeUnit.MILLISECONDS);
} }
latch.await(); latch.await();
@ -143,12 +122,8 @@ public class HashedWheelTimerTest {
int scheduledTasks = 100000; int scheduledTasks = 100000;
for (int i = 0; i < scheduledTasks; i++) { for (int i = 0; i < scheduledTasks; i++) {
final long start = System.nanoTime(); final long start = System.nanoTime();
timer.newTimeout(new TimerTask() { timer.newTimeout(timeout1 -> queue.add(
@Override TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)), timeout, TimeUnit.MILLISECONDS);
public void run(final Timeout timeout) throws Exception {
queue.add(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
}
}, timeout, TimeUnit.MILLISECONDS);
} }
for (int i = 0; i < scheduledTasks; i++) { for (int i = 0; i < scheduledTasks; i++) {
@ -234,31 +209,18 @@ public class HashedWheelTimerTest {
public void testOverflow() throws InterruptedException { public void testOverflow() throws InterruptedException {
final HashedWheelTimer timer = new HashedWheelTimer(); final HashedWheelTimer timer = new HashedWheelTimer();
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
Timeout timeout = timer.newTimeout(new TimerTask() { Timeout timeout = timer.newTimeout(timeout1 -> latch.countDown(), Long.MAX_VALUE, TimeUnit.MILLISECONDS);
@Override
public void run(Timeout timeout) {
latch.countDown();
}
}, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
assertFalse(latch.await(1, TimeUnit.SECONDS)); assertFalse(latch.await(1, TimeUnit.SECONDS));
timeout.cancel(); timeout.cancel();
timer.stop(); timer.stop();
} }
private static TimerTask createNoOpTimerTask() { private static TimerTask createNoOpTimerTask() {
return new TimerTask() { return timeout -> {
@Override
public void run(final Timeout timeout) throws Exception {
}
}; };
} }
private static TimerTask createCountDownLatchTimerTask(final CountDownLatch latch) { private static TimerTask createCountDownLatchTimerTask(final CountDownLatch latch) {
return new TimerTask() { return timeout -> latch.countDown();
@Override
public void run(final Timeout timeout) throws Exception {
latch.countDown();
}
};
} }
} }

View File

@ -102,17 +102,14 @@ public class NettyRuntimeTests {
final NettyRuntime.AvailableProcessorsHolder holder, final NettyRuntime.AvailableProcessorsHolder holder,
final CyclicBarrier barrier, final CyclicBarrier barrier,
final AtomicReference<IllegalStateException> reference) { final AtomicReference<IllegalStateException> reference) {
return new Runnable() { return () -> {
@Override await(barrier);
public void run() { try {
await(barrier); holder.availableProcessors();
try { } catch (final IllegalStateException e) {
holder.availableProcessors(); reference.set(e);
} catch (final IllegalStateException e) {
reference.set(e);
}
await(barrier);
} }
await(barrier);
}; };
} }
@ -120,28 +117,22 @@ public class NettyRuntimeTests {
public void testRacingGetAndSet() throws InterruptedException { public void testRacingGetAndSet() throws InterruptedException {
final NettyRuntime.AvailableProcessorsHolder holder = new NettyRuntime.AvailableProcessorsHolder(); final NettyRuntime.AvailableProcessorsHolder holder = new NettyRuntime.AvailableProcessorsHolder();
final CyclicBarrier barrier = new CyclicBarrier(3); final CyclicBarrier barrier = new CyclicBarrier(3);
final Thread get = new Thread(new Runnable() { final Thread get = new Thread(() -> {
@Override await(barrier);
public void run() { holder.availableProcessors();
await(barrier); await(barrier);
holder.availableProcessors();
await(barrier);
}
}); });
get.start(); get.start();
final AtomicReference<IllegalStateException> setException = new AtomicReference<>(); final AtomicReference<IllegalStateException> setException = new AtomicReference<>();
final Thread set = new Thread(new Runnable() { final Thread set = new Thread(() -> {
@Override await(barrier);
public void run() { try {
await(barrier); holder.setAvailableProcessors(2048);
try { } catch (final IllegalStateException e) {
holder.setAvailableProcessors(2048); setException.set(e);
} catch (final IllegalStateException e) {
setException.set(e);
}
await(barrier);
} }
await(barrier);
}); });
set.start(); set.start();

View File

@ -41,13 +41,10 @@ public class RecyclerTest {
final Recycler<HandledObject> recycler = newRecycler(1024); final Recycler<HandledObject> recycler = newRecycler(1024);
final AtomicBoolean collected = new AtomicBoolean(); final AtomicBoolean collected = new AtomicBoolean();
final AtomicReference<HandledObject> reference = new AtomicReference<>(); final AtomicReference<HandledObject> reference = new AtomicReference<>();
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(() -> {
@Override HandledObject object = recycler.get();
public void run() { // Store a reference to the HandledObject to ensure it is not collected when the run method finish.
HandledObject object = recycler.get(); reference.set(object);
// Store a reference to the HandledObject to ensure it is not collected when the run method finish.
reference.set(object);
}
}) { }) {
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
@ -86,23 +83,15 @@ public class RecyclerTest {
Recycler<HandledObject> recycler = newRecycler(1024); Recycler<HandledObject> recycler = newRecycler(1024);
final HandledObject object = recycler.get(); final HandledObject object = recycler.get();
final AtomicReference<IllegalStateException> exceptionStore = new AtomicReference<>(); final AtomicReference<IllegalStateException> exceptionStore = new AtomicReference<>();
final Thread thread1 = new Thread(new Runnable() { final Thread thread1 = new Thread(object::recycle);
@Override
public void run() {
object.recycle();
}
});
thread1.start(); thread1.start();
thread1.join(); thread1.join();
final Thread thread2 = new Thread(new Runnable() { final Thread thread2 = new Thread(() -> {
@Override try {
public void run() { object.recycle();
try { } catch (IllegalStateException e) {
object.recycle(); exceptionStore.set(e);
} catch (IllegalStateException e) {
exceptionStore.set(e);
}
} }
}); });
thread2.start(); thread2.start();

View File

@ -46,12 +46,9 @@ public class ThreadDeathWatcherTest {
} }
}; };
final Runnable task = new Runnable() { final Runnable task = () -> {
@Override if (!t.isAlive()) {
public void run() { latch.countDown();
if (!t.isAlive()) {
latch.countDown();
}
} }
}; };
@ -91,12 +88,7 @@ public class ThreadDeathWatcherTest {
} }
}; };
final Runnable task = new Runnable() { final Runnable task = () -> run.set(true);
@Override
public void run() {
run.set(true);
}
};
t.start(); t.start();
@ -121,16 +113,10 @@ public class ThreadDeathWatcherTest {
public void testThreadGroup() throws InterruptedException { public void testThreadGroup() throws InterruptedException {
final ThreadGroup group = new ThreadGroup("group"); final ThreadGroup group = new ThreadGroup("group");
final AtomicReference<ThreadGroup> capturedGroup = new AtomicReference<>(); final AtomicReference<ThreadGroup> capturedGroup = new AtomicReference<>();
final Thread thread = new Thread(group, new Runnable() { final Thread thread = new Thread(group, () -> {
@Override final Thread t = ThreadDeathWatcher.threadFactory.newThread(() -> {
public void run() { });
final Thread t = ThreadDeathWatcher.threadFactory.newThread(new Runnable() { capturedGroup.set(t.getThreadGroup());
@Override
public void run() {
}
});
capturedGroup.set(t.getThreadGroup());
}
}); });
thread.start(); thread.start();
thread.join(); thread.join();

View File

@ -27,11 +27,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
public class AbstractScheduledEventExecutorTest { public class AbstractScheduledEventExecutorTest {
private static final Runnable TEST_RUNNABLE = new Runnable() { private static final Runnable TEST_RUNNABLE = () -> {
@Override
public void run() {
}
}; };
private static final Callable<?> TEST_CALLABLE = Executors.callable(TEST_RUNNABLE); private static final Callable<?> TEST_CALLABLE = Executors.callable(TEST_RUNNABLE);

View File

@ -157,12 +157,7 @@ public class DefaultPromiseTest {
} }
}; };
GlobalEventExecutor.INSTANCE.execute(new Runnable() { GlobalEventExecutor.INSTANCE.execute(() -> promise.setSuccess(null));
@Override
public void run() {
promise.setSuccess(null);
}
});
promise.addListener(listener1).addListener(listener2).addListener(listener3); promise.addListener(listener1).addListener(listener2).addListener(listener3);
@ -217,12 +212,7 @@ public class DefaultPromiseTest {
final Map<Thread, DefaultPromise<Void>> promises = new HashMap<>(); final Map<Thread, DefaultPromise<Void>> promises = new HashMap<>();
for (int i = 0; i < numberOfAttempts; i++) { for (int i = 0; i < numberOfAttempts; i++) {
final DefaultPromise<Void> promise = new DefaultPromise<>(executor); final DefaultPromise<Void> promise = new DefaultPromise<>(executor);
final Thread thread = new Thread(new Runnable() { final Thread thread = new Thread(() -> promise.setSuccess(null));
@Override
public void run() {
promise.setSuccess(null);
}
});
promises.put(thread, promise); promises.put(thread, promise);
} }
@ -278,12 +268,7 @@ public class DefaultPromiseTest {
final CountDownLatch latch = new CountDownLatch(promiseChainLength); final CountDownLatch latch = new CountDownLatch(promiseChainLength);
if (runTestInExecutorThread) { if (runTestInExecutorThread) {
executor.execute(new Runnable() { executor.execute(() -> testStackOverFlowChainedFuturesA(executor, p, latch));
@Override
public void run() {
testStackOverFlowChainedFuturesA(executor, p, latch);
}
});
} else { } else {
testStackOverFlowChainedFuturesA(executor, p, latch); testStackOverFlowChainedFuturesA(executor, p, latch);
} }
@ -299,14 +284,11 @@ public class DefaultPromiseTest {
for (int i = 0; i < p.length; i ++) { for (int i = 0; i < p.length; i ++) {
final int finalI = i; final int finalI = i;
p[i] = new DefaultPromise<>(executor); p[i] = new DefaultPromise<>(executor);
p[i].addListener(new FutureListener<Void>() { p[i].addListener((FutureListener<Void>) future -> {
@Override if (finalI + 1 < p.length) {
public void operationComplete(Future<Void> future) throws Exception { p[finalI + 1].setSuccess(null);
if (finalI + 1 < p.length) {
p[finalI + 1].setSuccess(null);
}
latch.countDown();
} }
latch.countDown();
}); });
} }
@ -320,12 +302,7 @@ public class DefaultPromiseTest {
final CountDownLatch latch = new CountDownLatch(promiseChainLength); final CountDownLatch latch = new CountDownLatch(promiseChainLength);
if (runTestInExecutorThread) { if (runTestInExecutorThread) {
executor.execute(new Runnable() { executor.execute(() -> testStackOverFlowChainedFuturesA(executor, p, latch));
@Override
public void run() {
testStackOverFlowChainedFuturesA(executor, p, latch);
}
});
} else { } else {
testStackOverFlowChainedFuturesA(executor, p, latch); testStackOverFlowChainedFuturesA(executor, p, latch);
} }
@ -341,20 +318,12 @@ public class DefaultPromiseTest {
for (int i = 0; i < p.length; i ++) { for (int i = 0; i < p.length; i ++) {
final int finalI = i; final int finalI = i;
p[i] = new DefaultPromise<>(executor); p[i] = new DefaultPromise<>(executor);
p[i].addListener(new FutureListener<Void>() { p[i].addListener((FutureListener<Void>) future -> future.addListener((FutureListener<Void>) future1 -> {
@Override if (finalI + 1 < p.length) {
public void operationComplete(Future<Void> future) throws Exception { p[finalI + 1].setSuccess(null);
future.addListener(new FutureListener<Void>() {
@Override
public void operationComplete(Future<Void> future) throws Exception {
if (finalI + 1 < p.length) {
p[finalI + 1].setSuccess(null);
}
latch.countDown();
}
});
} }
}); latch.countDown();
}));
} }
p[0].setSuccess(null); p[0].setSuccess(null);
@ -379,12 +348,7 @@ public class DefaultPromiseTest {
final Promise<Void> promise = new DefaultPromise<>(executor); final Promise<Void> promise = new DefaultPromise<>(executor);
// Add a listener before completion so "lateListener" is used next time we add a listener. // Add a listener before completion so "lateListener" is used next time we add a listener.
promise.addListener(new FutureListener<Void>() { promise.addListener((FutureListener<Void>) future -> assertTrue(state.compareAndSet(0, 1)));
@Override
public void operationComplete(Future<Void> future) throws Exception {
assertTrue(state.compareAndSet(0, 1));
}
});
// Simulate write operation completing, which will execute listeners in another thread. // Simulate write operation completing, which will execute listeners in another thread.
if (cause == null) { if (cause == null) {
@ -394,12 +358,9 @@ public class DefaultPromiseTest {
} }
// Add a "late listener" // Add a "late listener"
promise.addListener(new FutureListener<Void>() { promise.addListener((FutureListener<Void>) future -> {
@Override assertTrue(state.compareAndSet(1, 2));
public void operationComplete(Future<Void> future) throws Exception { latch1.countDown();
assertTrue(state.compareAndSet(1, 2));
latch1.countDown();
}
}); });
// Wait for the listeners and late listeners to be completed. // Wait for the listeners and late listeners to be completed.
@ -408,27 +369,16 @@ public class DefaultPromiseTest {
// This is the important listener. A late listener that is added after all late listeners // This is the important listener. A late listener that is added after all late listeners
// have completed, and needs to update state before a read operation (on the same executor). // have completed, and needs to update state before a read operation (on the same executor).
executor.execute(new Runnable() { executor.execute(() -> promise.addListener((FutureListener<Void>) future -> {
@Override assertTrue(state.compareAndSet(2, 3));
public void run() { latch2.countDown();
promise.addListener(new FutureListener<Void>() { }));
@Override
public void operationComplete(Future<Void> future) throws Exception {
assertTrue(state.compareAndSet(2, 3));
latch2.countDown();
}
});
}
});
// Simulate a read operation being queued up in the executor. // Simulate a read operation being queued up in the executor.
executor.execute(new Runnable() { executor.execute(() -> {
@Override // This is the key, we depend upon the state being set in the next listener.
public void run() { assertEquals(3, state.get());
// This is the key, we depend upon the state being set in the next listener. latch2.countDown();
assertEquals(3, state.get());
latch2.countDown();
}
}); });
latch2.await(); latch2.await();
@ -440,17 +390,8 @@ public class DefaultPromiseTest {
private static void testPromiseListenerAddWhenComplete(Throwable cause) throws InterruptedException { private static void testPromiseListenerAddWhenComplete(Throwable cause) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
final Promise<Void> promise = new DefaultPromise<>(ImmediateEventExecutor.INSTANCE); final Promise<Void> promise = new DefaultPromise<>(ImmediateEventExecutor.INSTANCE);
promise.addListener(new FutureListener<Void>() { promise.addListener((FutureListener<Void>) future ->
@Override promise.addListener((FutureListener<Void>) future1 -> latch.countDown()));
public void operationComplete(Future<Void> future) throws Exception {
promise.addListener(new FutureListener<Void>() {
@Override
public void operationComplete(Future<Void> future) throws Exception {
latch.countDown();
}
});
}
});
if (cause == null) { if (cause == null) {
promise.setSuccess(null); promise.setSuccess(null);
} else { } else {
@ -463,29 +404,16 @@ public class DefaultPromiseTest {
EventExecutor executor = new TestEventExecutor(); EventExecutor executor = new TestEventExecutor();
int expectedCount = numListenersBefore + 2; int expectedCount = numListenersBefore + 2;
final CountDownLatch latch = new CountDownLatch(expectedCount); final CountDownLatch latch = new CountDownLatch(expectedCount);
final FutureListener<Void> listener = new FutureListener<Void>() { final FutureListener<Void> listener = future -> latch.countDown();
@Override
public void operationComplete(Future<Void> future) throws Exception {
latch.countDown();
}
};
final Promise<Void> promise = new DefaultPromise<>(executor); final Promise<Void> promise = new DefaultPromise<>(executor);
executor.execute(new Runnable() { executor.execute(() -> {
@Override for (int i = 0; i < numListenersBefore; i++) {
public void run() {
for (int i = 0; i < numListenersBefore; i++) {
promise.addListener(listener);
}
promise.setSuccess(null);
GlobalEventExecutor.INSTANCE.execute(new Runnable() {
@Override
public void run() {
promise.addListener(listener);
}
});
promise.addListener(listener); promise.addListener(listener);
} }
promise.setSuccess(null);
GlobalEventExecutor.INSTANCE.execute(() -> promise.addListener(listener));
promise.addListener(listener);
}); });
assertTrue("Should have notified " + expectedCount + " listeners", assertTrue("Should have notified " + expectedCount + " listeners",

View File

@ -55,30 +55,22 @@ public class DefaultThreadFactoryTest {
// holder for the thread factory, plays the role of a global singleton // holder for the thread factory, plays the role of a global singleton
final AtomicReference<DefaultThreadFactory> factory = new AtomicReference<>(); final AtomicReference<DefaultThreadFactory> factory = new AtomicReference<>();
final AtomicInteger counter = new AtomicInteger(); final AtomicInteger counter = new AtomicInteger();
final Runnable task = new Runnable() { final Runnable task = counter::incrementAndGet;
@Override
public void run() {
counter.incrementAndGet();
}
};
final AtomicReference<Throwable> interrupted = new AtomicReference<>(); final AtomicReference<Throwable> interrupted = new AtomicReference<>();
// create the thread factory, since we are running the thread group brother, the thread // create the thread factory, since we are running the thread group brother, the thread
// factory will now forever be tied to that group // factory will now forever be tied to that group
// we then create a thread from the factory to run a "task" for us // we then create a thread from the factory to run a "task" for us
final Thread first = new Thread(new ThreadGroup("brother"), new Runnable() { final Thread first = new Thread(new ThreadGroup("brother"), () -> {
@Override factory.set(new DefaultThreadFactory("test", false, Thread.NORM_PRIORITY, null));
public void run() { final Thread t = factory.get().newThread(task);
factory.set(new DefaultThreadFactory("test", false, Thread.NORM_PRIORITY, null)); t.start();
final Thread t = factory.get().newThread(task); try {
t.start(); t.join();
try { } catch (InterruptedException e) {
t.join(); interrupted.set(e);
} catch (InterruptedException e) { Thread.currentThread().interrupt();
interrupted.set(e);
Thread.currentThread().interrupt();
}
} }
}); });
first.start(); first.start();
@ -89,17 +81,14 @@ public class DefaultThreadFactoryTest {
// now we will use factory again, this time from a sibling thread group sister // now we will use factory again, this time from a sibling thread group sister
// if DefaultThreadFactory is "sticky" about thread groups, a security manager // if DefaultThreadFactory is "sticky" about thread groups, a security manager
// that forbids sibling thread groups from messing with each other will strike this down // that forbids sibling thread groups from messing with each other will strike this down
final Thread second = new Thread(new ThreadGroup("sister"), new Runnable() { final Thread second = new Thread(new ThreadGroup("sister"), () -> {
@Override final Thread t = factory.get().newThread(task);
public void run() { t.start();
final Thread t = factory.get().newThread(task); try {
t.start(); t.join();
try { } catch (InterruptedException e) {
t.join(); interrupted.set(e);
} catch (InterruptedException e) { Thread.currentThread().interrupt();
interrupted.set(e);
Thread.currentThread().interrupt();
}
} }
}); });
second.start(); second.start();
@ -119,12 +108,7 @@ public class DefaultThreadFactoryTest {
public void testDefaultThreadFactoryStickyThreadGroupConstructor() throws InterruptedException { public void testDefaultThreadFactoryStickyThreadGroupConstructor() throws InterruptedException {
final ThreadGroup sticky = new ThreadGroup("sticky"); final ThreadGroup sticky = new ThreadGroup("sticky");
runStickyThreadGroupTest( runStickyThreadGroupTest(
new Callable<DefaultThreadFactory>() { () -> new DefaultThreadFactory("test", false, Thread.NORM_PRIORITY, sticky),
@Override
public DefaultThreadFactory call() throws Exception {
return new DefaultThreadFactory("test", false, Thread.NORM_PRIORITY, sticky);
}
},
sticky); sticky);
} }
@ -135,21 +119,13 @@ public class DefaultThreadFactoryTest {
final ThreadGroup sticky = new ThreadGroup("sticky"); final ThreadGroup sticky = new ThreadGroup("sticky");
runStickyThreadGroupTest( runStickyThreadGroupTest(
new Callable<DefaultThreadFactory>() { () -> {
@Override final AtomicReference<DefaultThreadFactory> factory =
public DefaultThreadFactory call() throws Exception { new AtomicReference<>();
final AtomicReference<DefaultThreadFactory> factory = final Thread thread = new Thread(sticky, () -> factory.set(new DefaultThreadFactory("test")));
new AtomicReference<>(); thread.start();
final Thread thread = new Thread(sticky, new Runnable() { thread.join();
@Override return factory.get();
public void run() {
factory.set(new DefaultThreadFactory("test"));
}
});
thread.start();
thread.join();
return factory.get();
}
}, },
sticky); sticky);
} }
@ -174,12 +150,7 @@ public class DefaultThreadFactoryTest {
} }
}); });
runStickyThreadGroupTest( runStickyThreadGroupTest(
new Callable<DefaultThreadFactory>() { () -> new DefaultThreadFactory("test"),
@Override
public DefaultThreadFactory call() throws Exception {
return new DefaultThreadFactory("test");
}
},
sticky); sticky);
} finally { } finally {
System.setSecurityManager(current); System.setSecurityManager(current);
@ -192,23 +163,17 @@ public class DefaultThreadFactoryTest {
final AtomicReference<ThreadGroup> captured = new AtomicReference<>(); final AtomicReference<ThreadGroup> captured = new AtomicReference<>();
final AtomicReference<Throwable> exception = new AtomicReference<>(); final AtomicReference<Throwable> exception = new AtomicReference<>();
final Thread first = new Thread(new ThreadGroup("wrong"), new Runnable() { final Thread first = new Thread(new ThreadGroup("wrong"), () -> {
@Override final DefaultThreadFactory factory;
public void run() { try {
final DefaultThreadFactory factory; factory = callable.call();
try { } catch (Exception e) {
factory = callable.call(); exception.set(e);
} catch (Exception e) { throw new RuntimeException(e);
exception.set(e);
throw new RuntimeException(e);
}
final Thread t = factory.newThread(new Runnable() {
@Override
public void run() {
}
});
captured.set(t.getThreadGroup());
} }
final Thread t = factory.newThread(() -> {
});
captured.set(t.getThreadGroup());
}); });
first.start(); first.start();
first.join(); first.join();
@ -227,17 +192,11 @@ public class DefaultThreadFactoryTest {
final AtomicReference<ThreadGroup> firstCaptured = new AtomicReference<>(); final AtomicReference<ThreadGroup> firstCaptured = new AtomicReference<>();
final ThreadGroup firstGroup = new ThreadGroup("first"); final ThreadGroup firstGroup = new ThreadGroup("first");
final Thread first = new Thread(firstGroup, new Runnable() { final Thread first = new Thread(firstGroup, () -> {
@Override factory.set(new DefaultThreadFactory("sticky", false, Thread.NORM_PRIORITY, null));
public void run() { final Thread t = factory.get().newThread(() -> {
factory.set(new DefaultThreadFactory("sticky", false, Thread.NORM_PRIORITY, null)); });
final Thread t = factory.get().newThread(new Runnable() { firstCaptured.set(t.getThreadGroup());
@Override
public void run() {
}
});
firstCaptured.set(t.getThreadGroup());
}
}); });
first.start(); first.start();
first.join(); first.join();
@ -247,16 +206,10 @@ public class DefaultThreadFactoryTest {
final AtomicReference<ThreadGroup> secondCaptured = new AtomicReference<>(); final AtomicReference<ThreadGroup> secondCaptured = new AtomicReference<>();
final ThreadGroup secondGroup = new ThreadGroup("second"); final ThreadGroup secondGroup = new ThreadGroup("second");
final Thread second = new Thread(secondGroup, new Runnable() { final Thread second = new Thread(secondGroup, () -> {
@Override final Thread t = factory.get().newThread(() -> {
public void run() { });
final Thread t = factory.get().newThread(new Runnable() { secondCaptured.set(t.getThreadGroup());
@Override
public void run() {
}
});
secondCaptured.set(t.getThreadGroup());
}
}); });
second.start(); second.start();
second.join(); second.join();

View File

@ -82,14 +82,11 @@ public class FastThreadLocalTest {
@Test @Test
public void testMultipleSetRemove() throws Exception { public void testMultipleSetRemove() throws Exception {
final FastThreadLocal<String> threadLocal = new FastThreadLocal<>(); final FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
final Runnable runnable = new Runnable() { final Runnable runnable = () -> {
@Override threadLocal.set("1");
public void run() { threadLocal.remove();
threadLocal.set("1"); threadLocal.set("2");
threadLocal.remove(); threadLocal.remove();
threadLocal.set("2");
threadLocal.remove();
}
}; };
final int sizeWhenStart = ObjectCleaner.getLiveSetCount(); final int sizeWhenStart = ObjectCleaner.getLiveSetCount();
@ -110,18 +107,15 @@ public class FastThreadLocalTest {
public void testMultipleSetRemove_multipleThreadLocal() throws Exception { public void testMultipleSetRemove_multipleThreadLocal() throws Exception {
final FastThreadLocal<String> threadLocal = new FastThreadLocal<>(); final FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
final FastThreadLocal<String> threadLocal2 = new FastThreadLocal<>(); final FastThreadLocal<String> threadLocal2 = new FastThreadLocal<>();
final Runnable runnable = new Runnable() { final Runnable runnable = () -> {
@Override threadLocal.set("1");
public void run() { threadLocal.remove();
threadLocal.set("1"); threadLocal.set("2");
threadLocal.remove(); threadLocal.remove();
threadLocal.set("2"); threadLocal2.set("1");
threadLocal.remove(); threadLocal2.remove();
threadLocal2.set("1"); threadLocal2.set("2");
threadLocal2.remove(); threadLocal2.remove();
threadLocal2.set("2");
threadLocal2.remove();
}
}; };
final int sizeWhenStart = ObjectCleaner.getLiveSetCount(); final int sizeWhenStart = ObjectCleaner.getLiveSetCount();
@ -165,16 +159,13 @@ public class FastThreadLocalTest {
final TestFastThreadLocal threadLocal = new TestFastThreadLocal(); final TestFastThreadLocal threadLocal = new TestFastThreadLocal();
final TestFastThreadLocal threadLocal2 = new TestFastThreadLocal(); final TestFastThreadLocal threadLocal2 = new TestFastThreadLocal();
Runnable runnable = new Runnable() { Runnable runnable = () -> {
@Override if (callGet) {
public void run() { assertEquals(Thread.currentThread().getName(), threadLocal.get());
if (callGet) { assertEquals(Thread.currentThread().getName(), threadLocal2.get());
assertEquals(Thread.currentThread().getName(), threadLocal.get()); } else {
assertEquals(Thread.currentThread().getName(), threadLocal2.get()); threadLocal.set(Thread.currentThread().getName());
} else { threadLocal2.set(Thread.currentThread().getName());
threadLocal.set(Thread.currentThread().getName());
threadLocal2.set(Thread.currentThread().getName());
}
} }
}; };
Thread thread = fastThreadLocal ? new FastThreadLocalThread(runnable) : new Thread(runnable); Thread thread = fastThreadLocal ? new FastThreadLocalThread(runnable) : new Thread(runnable);

View File

@ -99,16 +99,10 @@ public class GlobalEventExecutorTest {
public void testThreadGroup() throws InterruptedException { public void testThreadGroup() throws InterruptedException {
final ThreadGroup group = new ThreadGroup("group"); final ThreadGroup group = new ThreadGroup("group");
final AtomicReference<ThreadGroup> capturedGroup = new AtomicReference<>(); final AtomicReference<ThreadGroup> capturedGroup = new AtomicReference<>();
final Thread thread = new Thread(group, new Runnable() { final Thread thread = new Thread(group, () -> {
@Override final Thread t = e.threadFactory.newThread(() -> {
public void run() { });
final Thread t = e.threadFactory.newThread(new Runnable() { capturedGroup.set(t.getThreadGroup());
@Override
public void run() {
}
});
capturedGroup.set(t.getThreadGroup());
}
}); });
thread.start(); thread.start();
thread.join(); thread.join();

View File

@ -68,14 +68,11 @@ public class NonStickyEventExecutorGroupTest {
final AtomicReference<Throwable> error = new AtomicReference<>(); final AtomicReference<Throwable> error = new AtomicReference<>();
List<Thread> threadList = new ArrayList<>(threads); List<Thread> threadList = new ArrayList<>(threads);
for (int i = 0 ; i < threads; i++) { for (int i = 0 ; i < threads; i++) {
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(() -> {
@Override try {
public void run() { execute(nonStickyGroup, startLatch);
try { } catch (Throwable cause) {
execute(nonStickyGroup, startLatch); error.compareAndSet(null, cause);
} catch (Throwable cause) {
error.compareAndSet(null, cause);
}
} }
}); });
threadList.add(thread); threadList.add(thread);
@ -106,12 +103,9 @@ public class NonStickyEventExecutorGroupTest {
final CountDownLatch firstCompleted = new CountDownLatch(1); final CountDownLatch firstCompleted = new CountDownLatch(1);
final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch latch = new CountDownLatch(2);
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
executor.execute(new Runnable() { executor.execute(() -> {
@Override firstCompleted.countDown();
public void run() { latch.countDown();
firstCompleted.countDown();
latch.countDown();
}
}); });
Assert.assertTrue(firstCompleted.await(1, TimeUnit.SECONDS)); Assert.assertTrue(firstCompleted.await(1, TimeUnit.SECONDS));
} }
@ -135,23 +129,20 @@ public class NonStickyEventExecutorGroupTest {
for (int i = 1 ; i <= tasks; i++) { for (int i = 1 ; i <= tasks; i++) {
final int id = i; final int id = i;
futures.add(executor.submit(new Runnable() { futures.add(executor.submit(() -> {
@Override try {
public void run() { if (cause.get() == null) {
try { int lastId = last.get();
if (cause.get() == null) { if (lastId >= id) {
int lastId = last.get(); cause.compareAndSet(null, new AssertionError(
if (lastId >= id) { "Out of order execution id(" + id + ") >= lastId(" + lastId + ')'));
cause.compareAndSet(null, new AssertionError( }
"Out of order execution id(" + id + ") >= lastId(" + lastId + ')')); if (!last.compareAndSet(lastId, id)) {
} cause.compareAndSet(null, new AssertionError("Concurrent execution of tasks"));
if (!last.compareAndSet(lastId, id)) {
cause.compareAndSet(null, new AssertionError("Concurrent execution of tasks"));
}
} }
} finally {
latch.countDown();
} }
} finally {
latch.countDown();
} }
})); }));
} }

View File

@ -178,13 +178,9 @@ public class PromiseCombinerTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static void mockListener(final Promise<Void> p, final GenericFutureListenerConsumer consumer) { private static void mockListener(final Promise<Void> p, final GenericFutureListenerConsumer consumer) {
doAnswer(new Answer<Promise<Void>>() { doAnswer(invocation -> {
@SuppressWarnings({ "unchecked", "raw-types" }) consumer.accept((GenericFutureListener) invocation.getArgument(0));
@Override return p;
public Promise<Void> answer(InvocationOnMock invocation) throws Throwable {
consumer.accept((GenericFutureListener) invocation.getArgument(0));
return p;
}
}).when(p).addListener(any(GenericFutureListener.class)); }).when(p).addListener(any(GenericFutureListener.class));
} }

View File

@ -60,11 +60,8 @@ public class SingleThreadEventExecutorTest {
private static void executeShouldFail(Executor executor) { private static void executeShouldFail(Executor executor) {
try { try {
executor.execute(new Runnable() { executor.execute(() -> {
@Override // Noop.
public void run() {
// Noop.
}
}); });
Assert.fail(); Assert.fail();
} catch (RejectedExecutionException expected) { } catch (RejectedExecutionException expected) {
@ -133,34 +130,28 @@ public class SingleThreadEventExecutorTest {
}; };
try { try {
final Promise<Void> promise = executor.newPromise(); final Promise<Void> promise = executor.newPromise();
executor.execute(new Runnable() { executor.execute(() -> {
@Override try {
public void run() { Set<Callable<Boolean>> set = Collections.singleton(() -> {
try { promise.setFailure(new AssertionError("Should never execute the Callable"));
Set<Callable<Boolean>> set = Collections.singleton(new Callable<Boolean>() { return Boolean.TRUE;
@Override });
public Boolean call() throws Exception { if (any) {
promise.setFailure(new AssertionError("Should never execute the Callable")); if (timeout) {
return Boolean.TRUE; executor.invokeAny(set, 10, TimeUnit.SECONDS);
}
});
if (any) {
if (timeout) {
executor.invokeAny(set, 10, TimeUnit.SECONDS);
} else {
executor.invokeAny(set);
}
} else { } else {
if (timeout) { executor.invokeAny(set);
executor.invokeAll(set, 10, TimeUnit.SECONDS); }
} else { } else {
executor.invokeAll(set); if (timeout) {
} executor.invokeAll(set, 10, TimeUnit.SECONDS);
} else {
executor.invokeAll(set);
} }
promise.setFailure(new AssertionError("Should never reach here"));
} catch (Throwable cause) {
promise.setFailure(cause);
} }
promise.setFailure(new AssertionError("Should never reach here"));
} catch (Throwable cause) {
promise.setFailure(cause);
} }
}); });
promise.syncUninterruptibly(); promise.syncUninterruptibly();

Some files were not shown because too many files have changed in this diff Show More