netty 校验_Netty如何测试 ChannelHandler

本节的内容是介绍Netty中要如何通过 EmbeddedChannel 对 ChannelHandler 进行测试。

测试入站消息

我们先来编写一个简单的 ByteToMessageDecoder 实现,在有足够的数据可以读取的情况下将产生固定大小的包,如果没有足够的数据可以读取,则会等待下一个数据块并再次检查是否可以产生一个完整包。

如图所示,它可能会占用一个以上的“event”以获取足够的字节产生一个数据包,并将它传递到 ChannelPipeline 中的下一个 ChannelHandler,

Figure 10.2 Decoding via FixedLengthFrameDecoder

实现如下:

Listing 10.1 FixedLengthFrameDecoder implementationpublic class FixedLengthFrameDecoder extends ByteToMessageDecoder { //1

private final int frameLength;

public FixedLengthFrameDecoder(int frameLength) { //2

if (frameLength <= 0) {

throw new IllegalArgumentException(

"frameLength must be a positive integer: " + frameLength);

}

this.frameLength = frameLength;

}

@Override

protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {

if (in.readableBytes() >= frameLength) { //3

ByteBuf buf = in.readBytes(frameLength);//4

out.add(buf); //5

}

}

}继承 ByteToMessageDecoder 用来处理入站的字节并将他们解码为消息

指定产出的帧的长度

检查是否有足够的字节用于读到下个帧

从 ByteBuf 读取新帧

添加帧到解码好的消息 List

下面是单元测试的例子,使用 EmbeddedChannel

Listing 10.2 Test the FixedLengthFrameDecoderpublic class FixedLengthFrameDecoderTest {

@Test //1

public void testFramesDecoded() {

ByteBuf buf = Unpooled.buffer(); //2

for (int i = 0; i < 9; i++) {

buf.writeByte(i);

}

ByteBuf input = buf.duplicate();

EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3)); //3

Assert.assertFalse(channel.writeInbound(input.readBytes(2))); //4

Assert.assertTrue(channel.writeInbound(input.readBytes(7)));

Assert.assertTrue(channel.finish()); //5

ByteBuf read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

Assert.assertNull(channel.readInbound());

buf.release();

}

@Test

public void testFramesDecoded2() {

ByteBuf buf = Unpooled.buffer();

for (int i = 0; i < 9; i++) {

buf.writeByte(i);

}

ByteBuf input = buf.duplicate();

EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3));

Assert.assertFalse(channel.writeInbound(input.readBytes(2)));

Assert.assertTrue(channel.writeInbound(input.readBytes(7)));

Assert.assertTrue(channel.finish());

ByteBuf read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

read = (ByteBuf) channel.readInbound();

Assert.assertEquals(buf.readSlice(3), read);

read.release();

Assert.assertNull(channel.readInbound());

buf.release();

}

}测试增加 @Test 注解

新建 ByteBuf 并用字节填充它

新增 EmbeddedChannel 并添加 FixedLengthFrameDecoder 用于测试

写数据到 EmbeddedChannel

标记 channel 已经完成

读产生的消息并且校验

如上面代码,testFramesDecoded() 方法想测试一个 ByteBuf,这个ByteBuf 包含9个可读字节,被解码成包含了3个可读字节的 ByteBuf。你可能注意到,它写入9字节到通道是通过调用 writeInbound() 方法,之后再执行 finish() 来将 EmbeddedChannel 标记为已完成,最后调用readInbound() 方法来获取 EmbeddedChannel 中的数据,直到没有可读字节。testFramesDecoded2() 方法采取同样的方式,但有一个区别就是入站ByteBuf分两步写的,当调用 writeInbound(input.readBytes(2)) 后返回 false 时,FixedLengthFrameDecoder 值会产生输出,至少有3个字节是可读,testFramesDecoded2() 测试的工作相当于testFramesDecoded()。

Testing outbound messages

测试的处理出站消息类似于我们刚才看到的一切。这个例子将使用的实现MessageToMessageEncoder:AbsIntegerEncoder。当收到 flush() 它将从 ByteBuf 读取4字节整数并给每个执行Math.abs()。

每个整数接着写入 ChannelHandlerPipeline

图10.3显示了逻辑。

Figure 10.3 Encoding via AbsIntegerEncoder

示例如下:

Listing 10.3 AbsIntegerEncoderpublic class AbsIntegerEncoder extends MessageToMessageEncoder { //1

@Override

protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List out) throws Exception {

while (in.readableBytes() >= 4) { //2

int value = Math.abs(in.readInt());//3

out.add(value); //4

}

}

}继承 MessageToMessageEncoder 用于编码消息到另外一种格式

检查是否有足够的字节用于编码

读取下一个输入 ByteBuf 产出的 int 值,并计算绝对值

写 int 到编码的消息 List

在前面的示例中,我们将使用 EmbeddedChannel 测试代码。清单10.4

Listing 10.4 Test the AbsIntegerEncoderpublic class AbsIntegerEncoderTest {

@Test //1

public void testEncoded() {

ByteBuf buf = Unpooled.buffer(); //2

for (int i = 1; i < 10; i++) {

buf.writeInt(i * -1);

}

EmbeddedChannel channel = new EmbeddedChannel(new AbsIntegerEncoder()); //3

Assert.assertTrue(channel.writeOutbound(buf)); //4

Assert.assertTrue(channel.finish()); //5

for (int i = 1; i < 10; i++) {

Assert.assertEquals(i, channel.readOutbound()); //6

}

Assert.assertNull(channel.readOutbound());

}

}用 @Test 标记

新建 ByteBuf 并写入负整数

新建 EmbeddedChannel 并安装 AbsIntegerEncoder 来测试

写 ByteBuf 并预测 readOutbound() 产生的数据

标记 channel 已经完成

读取产生到的消息,检查负值已经编码为绝对值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值