Skip to content

Commit

Permalink
chapter09 unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
sh-cho committed May 1, 2024
1 parent 492a6b1 commit 9e4e121
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 2 deletions.
21 changes: 21 additions & 0 deletions chapter09-unit-testing/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
id("java-conventions")
}

dependencies {
implementation(project(":core"))

implementation(platform(libs.netty.bom))
implementation("io.netty:netty-all")

testImplementation(platform(libs.junit.bom))
testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
useJUnitPlatform()

testLogging {
showStandardStreams = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.joebrothers.chapter09;

import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;

public class AbsIntegerEncoder extends MessageToMessageEncoder<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
throws Exception {
while (in.readableBytes() >= 4) {
final int value = Math.abs(in.readInt());
out.add(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.joebrothers.chapter09;

import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class FixedLengthFrameDecoder extends ByteToMessageDecoder {

private final int frameLength;

public FixedLengthFrameDecoder(int frameLength) {
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<Object> out)
throws Exception {
while (in.readableBytes() >= frameLength) {
final ByteBuf buf = in.readBytes(frameLength);
out.add(buf);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.joebrothers.chapter09;

import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.TooLongFrameException;

public class FrameChunkDecoder extends ByteToMessageDecoder {

private final int maxFrameSize;

public FrameChunkDecoder(int maxFrameSize) {
if (maxFrameSize <= 0) {
throw new IllegalArgumentException("maxFrameSize must be a positive number: " + maxFrameSize);
}

this.maxFrameSize = maxFrameSize;
}

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
throws Exception {
final int readableBytes = in.readableBytes();
if (readableBytes > maxFrameSize) {
// discard
in.clear();
throw new TooLongFrameException();
}
final ByteBuf buf = in.readBytes(readableBytes);
out.add(buf);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.joebrothers.chapter09;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;

class AbsIntegerEncoderTest {

@Test
void testEncode() {
final ByteBuf buf = Unpooled.buffer();
for (int i = 1; i < 10; i++) {
buf.writeInt(i * -1);
}

final EmbeddedChannel channel = new EmbeddedChannel(new AbsIntegerEncoder());

// Write
assertTrue(channel.writeOutbound(buf));
assertTrue(channel.finish());

// Read
for (int i = 1; i < 10; i++) {
assertEquals(i, (int) channel.readOutbound());
}
assertNull(channel.readOutbound());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.joebrothers.chapter09;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;

class FixedLengthFrameDecoderTest {

@Test
public void testFramesDecoded() {
final ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}

final ByteBuf input = buf.duplicate();
final EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3));

// Write bytes
assertTrue(channel.writeInbound(input.retain())); // retain!
assertTrue(channel.finish());

// Read messages
ByteBuf read;
for (int i=0; i<3; i++) {
read = channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();
}

assertNull(channel.readInbound());
buf.release();
}

@Test
public void testFramesDecoded2() {
final ByteBuf buf = Unpooled.buffer();
for (int i=0; i<9; i++) {
buf.writeByte(i);
}

final ByteBuf input = buf.duplicate();
final EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3));
assertFalse(channel.writeInbound(input.readBytes(2))); // frame is not ready to be read!
assertTrue(channel.writeInbound(input.readBytes(7)));
assertTrue(channel.finish());

ByteBuf read;
for (int i=0; i<3; i++) {
read = channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();
}

assertNull(channel.readInbound());
buf.release();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.joebrothers.chapter09;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import org.junit.jupiter.api.Test;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.TooLongFrameException;

class FrameChunkDecoderTest {

@Test
void testFramesDecoded() {
final ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}
final ByteBuf input = buf.duplicate();

final EmbeddedChannel channel = new EmbeddedChannel(new FrameChunkDecoder(3));
assertTrue(channel.writeInbound(input.readBytes(2)));

try {
// bigger than max size
channel.writeInbound(input.readBytes(4));
fail();
} catch (TooLongFrameException e) {
// expected
}

assertTrue(channel.writeInbound(input.readBytes(3)));
assertTrue(channel.finish());

// Read
ByteBuf read;
{
read = channel.readInbound();
assertEquals(buf.readSlice(2), read);
read.release();
}
{
read = channel.readInbound();
assertEquals(buf.skipBytes(4).readSlice(3), read);
read.release();
}

buf.release();
}
}
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
findbugs = "3.0.2"
guava = "32.1.3-jre"
javax-annotation = "1.3.2"
junit-jupiter = "5.10.0"
junit-bom = "5.10.0"
netty-bom = "4.1.108.Final"

[libraries]
findbugs = { module = "com.google.code.findbugs:jsr305", version.ref = "findbugs" }
guava = { module = "com.google.guava:guava", version.ref = "guava" }
javax-annotation = { module = "javax.annotation:javax.annotation-api", version.ref = "javax-annotation" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit-bom" }
netty-bom = { module = "io.netty:netty-bom", version.ref = "netty-bom" }
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ plugins {
rootProject.name = "netty-practice"
include("core")
include("chapter04-transport")
include("chapter09-unit-testing")
include("echo-client")
include("echo-server")

0 comments on commit 9e4e121

Please sign in to comment.