fa84e2b3af
Motiviation: Http2FrameCodecTest and Http2MultiplexCodecTest were quite fragile and often not went through the whole pipeline which made testing sometimes hard and error-prone. Modification: - Refactor tests to have data flow through the whole pipeline and so made the test more robust (by testing the while implementation). Result: Easier to write tests for the codecs in the future and more robust testing in general. Beside this it also fixes https://github.com/netty/netty/issues/6036.
123 lines
4.0 KiB
Java
123 lines
4.0 KiB
Java
/*
|
|
* Copyright 2016 The Netty Project
|
|
*
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
package io.netty.handler.codec.http2;
|
|
|
|
import io.netty.buffer.ByteBuf;
|
|
import io.netty.buffer.ByteBufAllocator;
|
|
import io.netty.channel.Channel;
|
|
import io.netty.channel.ChannelConfig;
|
|
import io.netty.channel.ChannelHandler;
|
|
import io.netty.channel.ChannelHandler.Sharable;
|
|
import io.netty.channel.ChannelInitializer;
|
|
import io.netty.channel.RecvByteBufAllocator;
|
|
import io.netty.util.UncheckedBooleanSupplier;
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
/**
|
|
* Channel initializer useful in tests.
|
|
*/
|
|
@Sharable
|
|
public class TestChannelInitializer extends ChannelInitializer<Channel> {
|
|
ChannelHandler handler;
|
|
AtomicInteger maxReads;
|
|
|
|
@Override
|
|
public void initChannel(Channel channel) {
|
|
if (handler != null) {
|
|
channel.pipeline().addLast(handler);
|
|
handler = null;
|
|
}
|
|
if (maxReads != null) {
|
|
channel.config().setRecvByteBufAllocator(new TestNumReadsRecvByteBufAllocator(maxReads));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Designed to read a single byte at a time to control the number of reads done at a fine granularity.
|
|
*/
|
|
static final class TestNumReadsRecvByteBufAllocator implements RecvByteBufAllocator {
|
|
private final AtomicInteger numReads;
|
|
private TestNumReadsRecvByteBufAllocator(AtomicInteger numReads) {
|
|
this.numReads = numReads;
|
|
}
|
|
|
|
@Override
|
|
public ExtendedHandle newHandle() {
|
|
return new ExtendedHandle() {
|
|
private int attemptedBytesRead;
|
|
private int lastBytesRead;
|
|
private int numMessagesRead;
|
|
@Override
|
|
public ByteBuf allocate(ByteBufAllocator alloc) {
|
|
return alloc.ioBuffer(guess(), guess());
|
|
}
|
|
|
|
@Override
|
|
public int guess() {
|
|
return 1; // only ever allocate buffers of size 1 to ensure the number of reads is controlled.
|
|
}
|
|
|
|
@Override
|
|
public void reset(ChannelConfig config) {
|
|
numMessagesRead = 0;
|
|
}
|
|
|
|
@Override
|
|
public void incMessagesRead(int numMessages) {
|
|
numMessagesRead += numMessages;
|
|
}
|
|
|
|
@Override
|
|
public void lastBytesRead(int bytes) {
|
|
lastBytesRead = bytes;
|
|
}
|
|
|
|
@Override
|
|
public int lastBytesRead() {
|
|
return lastBytesRead;
|
|
}
|
|
|
|
@Override
|
|
public void attemptedBytesRead(int bytes) {
|
|
attemptedBytesRead = bytes;
|
|
}
|
|
|
|
@Override
|
|
public int attemptedBytesRead() {
|
|
return attemptedBytesRead;
|
|
}
|
|
|
|
@Override
|
|
public boolean continueReading() {
|
|
return numMessagesRead < numReads.get();
|
|
}
|
|
|
|
@Override
|
|
public boolean continueReading(UncheckedBooleanSupplier maybeMoreDataSupplier) {
|
|
return continueReading();
|
|
}
|
|
|
|
@Override
|
|
public void readComplete() {
|
|
// Nothing needs to be done or adjusted after each read cycle is completed.
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|