301 lines
11 KiB
Java
301 lines
11 KiB
Java
package mc.protocol.io;
|
|
|
|
import mc.protocol.io.coder.ByteArrayNetInputStream;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.params.ParameterizedTest;
|
|
import org.junit.jupiter.params.provider.Arguments;
|
|
import org.junit.jupiter.params.provider.MethodSource;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Random;
|
|
import java.util.UUID;
|
|
import java.util.stream.Stream;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
class NetInputStreamTest {
|
|
|
|
private Random random;
|
|
private ByteArrayOutputStream baos;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
random = new Random(System.currentTimeMillis());
|
|
baos = new ByteArrayOutputStream();
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsReadBoolean")
|
|
void readBoolean(byte sourceByte, boolean expectedValue) {
|
|
baos.write(sourceByte);
|
|
|
|
NetInputStream netInputStream = createNetInputStream(baos.toByteArray());
|
|
|
|
assertEquals(expectedValue, netInputStream.readBoolean());
|
|
}
|
|
|
|
@Test
|
|
void readByte() {
|
|
byte b = Integer.valueOf(random.nextInt()).byteValue();
|
|
baos.write(b);
|
|
|
|
assertEquals(b, createNetInputStream(baos.toByteArray()).readByte());
|
|
assertEquals(b, createNetInputStream(baos.toByteArray()).read());
|
|
|
|
baos.reset();
|
|
baos.write(128);
|
|
assertEquals(-128, createNetInputStream(baos.toByteArray()).readByte());
|
|
}
|
|
|
|
@Test
|
|
void readUnsignedByte() {
|
|
int value = 128;
|
|
baos.write(value);
|
|
|
|
assertEquals(value, createNetInputStream(baos.toByteArray()).readUnsignedByte());
|
|
}
|
|
|
|
@Test
|
|
void readShort() throws IOException {
|
|
int value = Integer.valueOf(random.nextInt()).shortValue();
|
|
createDataOutputStream().writeShort(value);
|
|
|
|
assertEquals(value, createNetInputStream(baos.toByteArray()).readShort());
|
|
|
|
baos.reset();
|
|
createDataOutputStream().writeShort(32768);
|
|
assertEquals(-32768, createNetInputStream(baos.toByteArray()).readShort());
|
|
}
|
|
|
|
@Test
|
|
void readUnsignedShort() throws IOException {
|
|
int value = 32768;
|
|
createDataOutputStream().writeShort(value);
|
|
|
|
assertEquals(value, createNetInputStream(baos.toByteArray()).readUnsignedShort());
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsReadUnsignedByte")
|
|
void readUnsignedByte(byte sourceByte, int expectedValue) {
|
|
baos.write(sourceByte);
|
|
|
|
assertEquals(expectedValue, createNetInputStream(baos.toByteArray()).readUnsignedByte());
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsReadString")
|
|
void readString(String string) throws IOException {
|
|
final byte[] strBytes = string.getBytes(StandardCharsets.UTF_8);
|
|
final byte[] bytes = new byte[strBytes.length + 1];
|
|
bytes[0] = (byte) string.codePoints().count(); // здесь считается, что размер поместится в один байт
|
|
System.arraycopy(strBytes, 0, bytes, 1, strBytes.length);
|
|
|
|
baos.write(bytes);
|
|
|
|
assertEquals(string, createNetInputStream(baos.toByteArray()).readString());
|
|
}
|
|
|
|
@Test
|
|
void readString_overSize() throws IOException {
|
|
String string = "123";
|
|
final byte[] strBytes = string.getBytes(StandardCharsets.UTF_8);
|
|
final byte[] bytes = new byte[strBytes.length + 1];
|
|
final int length = string.length();
|
|
bytes[0] = (byte) (length + 1); // здесь считается, что размер поместится в один байт
|
|
System.arraycopy(strBytes, 0, bytes, 1, strBytes.length);
|
|
|
|
baos.write(bytes);
|
|
|
|
assertThrows(DecoderException.class, () -> createNetInputStream(baos.toByteArray()).readString(length));
|
|
}
|
|
|
|
@Test
|
|
void readString_lessZero() throws IOException {
|
|
String string = "123";
|
|
final byte[] strBytes = string.getBytes(StandardCharsets.UTF_8);
|
|
final byte[] bytes = new byte[strBytes.length + 5];
|
|
bytes[0] = (byte) 0xFF;
|
|
bytes[1] = (byte) 0xFF;
|
|
bytes[2] = (byte) 0xFF;
|
|
bytes[3] = (byte) 0xFF;
|
|
bytes[4] = (byte) 0x0F;
|
|
System.arraycopy(strBytes, 0, bytes, 5, strBytes.length);
|
|
|
|
baos.write(bytes);
|
|
|
|
assertThrows(DecoderException.class, () -> createNetInputStream(baos.toByteArray()).readString(-1));
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsReadVarInt")
|
|
void readVarInt(byte[] sourceBytes, int expectedValue) throws IOException {
|
|
baos.write(sourceBytes);
|
|
|
|
assertEquals(expectedValue, createNetInputStream(baos.toByteArray()).readVarInt());
|
|
}
|
|
|
|
@Test
|
|
void readVarInt_tooBig() throws IOException {
|
|
baos.write(new byte[]{ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x0F });
|
|
|
|
assertEquals(-1, createNetInputStream(baos.toByteArray()).readVarInt());
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource({"paramsReadVarInt", "paramsReadVarLong"})
|
|
void readVarLong(byte[] sourceBytes, long expectedValue) throws IOException {
|
|
baos.write(sourceBytes);
|
|
|
|
assertEquals(expectedValue, createNetInputStream(baos.toByteArray()).readVarLong());
|
|
}
|
|
|
|
@Test
|
|
void readVarLong_tooBig() throws IOException {
|
|
baos.write(new byte[]{ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
|
|
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
|
|
(byte) 0xFF, (byte) 0x0F });
|
|
|
|
assertEquals(-1, createNetInputStream(baos.toByteArray()).readVarLong());
|
|
}
|
|
|
|
@Test
|
|
void readUUID() throws IOException {
|
|
final UUID uuid = UUID.randomUUID();
|
|
final long mostSignificantBits = uuid.getMostSignificantBits();
|
|
final long leastSignificantBits = uuid.getLeastSignificantBits();
|
|
|
|
baos.write(new byte[]{
|
|
(byte) ((mostSignificantBits >>> 56) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 48) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 40) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 32) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 24) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 16) & 0xFF),
|
|
(byte) ((mostSignificantBits >>> 8) & 0xFF),
|
|
(byte) (mostSignificantBits & 0xFF)
|
|
});
|
|
baos.write(new byte[]{
|
|
(byte) ((leastSignificantBits >>> 56) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 48) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 40) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 32) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 24) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 16) & 0xFF),
|
|
(byte) ((leastSignificantBits >>> 8) & 0xFF),
|
|
(byte) (leastSignificantBits & 0xFF)
|
|
});
|
|
|
|
assertEquals(uuid, createNetInputStream(baos.toByteArray()).readUUID());
|
|
}
|
|
|
|
@Test
|
|
void readBytes() throws IOException {
|
|
byte[] bytes = new byte[128];
|
|
random.nextBytes(bytes);
|
|
baos.write(bytes);
|
|
|
|
byte[] actualBytes = new byte[128];
|
|
createNetInputStream(baos.toByteArray()).readBytes(actualBytes);
|
|
|
|
assertArrayEquals(bytes, actualBytes);
|
|
|
|
actualBytes = new byte[128];
|
|
int read = createNetInputStream(baos.toByteArray()).read(actualBytes);
|
|
|
|
assertArrayEquals(bytes, actualBytes);
|
|
assertEquals(128, read);
|
|
}
|
|
|
|
@Test
|
|
void read_offset() throws IOException {
|
|
byte[] bytes = new byte[128];
|
|
random.nextBytes(bytes);
|
|
baos.write(bytes);
|
|
|
|
byte[] actualBytes = new byte[128];
|
|
int read = createNetInputStream(baos.toByteArray()).read(actualBytes, 3, 11);
|
|
assertEquals(11, read);
|
|
|
|
byte[] buff1 = new byte[11];
|
|
System.arraycopy(bytes, 0, buff1, 0, 11);
|
|
byte[] buff2 = new byte[11];
|
|
System.arraycopy(actualBytes, 3, buff2, 0, 11);
|
|
|
|
assertArrayEquals(buff1, buff2);
|
|
}
|
|
|
|
private NetInputStream createNetInputStream(byte[] buffer) {
|
|
return new ByteArrayNetInputStream(buffer);
|
|
}
|
|
|
|
private DataOutputStream createDataOutputStream() {
|
|
return new DataOutputStream(baos);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsReadBoolean() {
|
|
return Stream.of(
|
|
Arguments.of((byte) 0x00, false),
|
|
Arguments.of((byte) 0x01, true)
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsReadUnsignedByte() {
|
|
return Stream.of(
|
|
Arguments.of((byte) 30, 30),
|
|
Arguments.of((byte) (0xFF & 130), 130)
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsReadString() {
|
|
return Stream.of(
|
|
Arguments.of(""),
|
|
Arguments.of("Latin"),
|
|
Arguments.of("Кириллица"),
|
|
Arguments.of("العربية"),
|
|
Arguments.of("ﬦﬣﬡ"), // Алфавитные формы представления
|
|
Arguments.of("\uD800\uDD07") // Эгейские цифры, [один]
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsReadVarInt() {
|
|
return Stream.of(
|
|
Arguments.of(new byte[]{ 0x78 }, 120),
|
|
Arguments.of(new byte[]{ (byte) 0xE0, 0x5D }, 12000),
|
|
Arguments.of(new byte[]{ (byte) 0xC0, (byte) 0xA9, 0x07 }, 120000),
|
|
Arguments.of(new byte[]{ (byte) 0x80, (byte) 0x9C, (byte) 0x9C, (byte) 0x39 }, 120_000_000),
|
|
Arguments.of(new byte[]{ (byte) 0x80, (byte) 0x98, (byte) 0x9A, (byte) 0xBC, 0x04 }, 1_200_000_000)
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsReadVarLong() {
|
|
return Stream.of(
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0xF0, (byte) 0x85, (byte) 0xDA, 0x2C },
|
|
12_000_000_000L),
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0xE0, (byte) 0xBA, (byte) 0x84, (byte) 0xBF, 0x03 },
|
|
120_000_000_000L),
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xF3, (byte) 0xBD, (byte) 0x9F, (byte) 0xDD,
|
|
0x02 },
|
|
12_000_000_000_000L),
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xEC, (byte) 0xAD, (byte) 0xCC, (byte) 0xEC,
|
|
(byte) 0x90, 0x02},
|
|
1_200_000_000_000_000L),
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xB0, (byte) 0xE8, (byte) 0xD3, (byte) 0xEB,
|
|
(byte) 0x94, (byte) 0xD5, 0x01 },
|
|
120_000_000_000_000_000L),
|
|
Arguments.of(
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80,
|
|
(byte) 0x80, (byte) 0x80, (byte) 0x80, 0x01 },
|
|
Long.MIN_VALUE)
|
|
);
|
|
}
|
|
} |