230 lines
8.8 KiB
Java
230 lines
8.8 KiB
Java
package mc.protocol.io;
|
|
|
|
import org.apache.commons.lang3.RandomStringUtils;
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
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.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.assertArrayEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
class NetOutputStreamTest {
|
|
|
|
private static Random random;
|
|
|
|
@BeforeAll
|
|
static void setUp() {
|
|
random = new Random(System.currentTimeMillis());
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsWriteBoolean")
|
|
void writeBoolean(boolean sourceValue, byte expectedByte) {
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeBoolean(sourceValue);
|
|
|
|
assertEquals(expectedByte, toByteArray(netOutputStream)[0]);
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsWriteByte")
|
|
void writeByte(byte sourceValue, byte expectedByte) throws IOException {
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeByte(sourceValue);
|
|
|
|
assertEquals(expectedByte, toByteArray(netOutputStream)[0]);
|
|
|
|
netOutputStream = createNetOutputStream();
|
|
netOutputStream.write(sourceValue);
|
|
|
|
assertEquals(expectedByte, toByteArray(netOutputStream)[0]);
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsWriteString")
|
|
void writeString(String string) {
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeString(string);
|
|
|
|
byte[] bytes = toByteArray(netOutputStream);
|
|
int length = bytes[0];
|
|
assertEquals(string.codePoints().count(), length);
|
|
|
|
byte[] dataBytes = new byte[bytes.length - 1];
|
|
System.arraycopy(bytes, 1, dataBytes, 0, dataBytes.length);
|
|
assertEquals(string, new String(dataBytes, StandardCharsets.UTF_8));
|
|
}
|
|
|
|
@Test
|
|
void writeString_overSize() {
|
|
String overSizeString = RandomStringUtils.randomAscii(Short.MAX_VALUE + Short.MAX_VALUE);
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeString(overSizeString);
|
|
|
|
NetInputStream netInputStream = new ByteArrayNetInputStream(toByteArray(netOutputStream));
|
|
String actualString = netInputStream.readString();
|
|
|
|
String expectedString = overSizeString.substring(0, Short.MAX_VALUE);
|
|
|
|
assertEquals(expectedString, actualString);
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource("paramsWriteVarInt")
|
|
void writeVarInt(int sourceValue, byte[] expectedBytes) {
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeVarInt(sourceValue);
|
|
|
|
assertArrayEquals(expectedBytes, toByteArray(netOutputStream));
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@MethodSource({"paramsWriteVarInt", "paramsWriteVarLong"})
|
|
void writeVarLong(long sourceValue, byte[] expectedBytes) {
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeVarLong(sourceValue);
|
|
|
|
assertArrayEquals(expectedBytes, toByteArray(netOutputStream));
|
|
}
|
|
|
|
@Test
|
|
void writeUUID() {
|
|
final UUID uuid = UUID.randomUUID();
|
|
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeUUID(uuid);
|
|
|
|
final long mostSignificantBits = uuid.getMostSignificantBits();
|
|
final long leastSignificantBits = uuid.getLeastSignificantBits();
|
|
|
|
assertArrayEquals(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),
|
|
|
|
(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) },
|
|
toByteArray(netOutputStream));
|
|
}
|
|
|
|
@Test
|
|
void writeBytes() throws IOException {
|
|
byte[] bytes = new byte[128];
|
|
random.nextBytes(bytes);
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.writeBytes(bytes);
|
|
|
|
assertArrayEquals(bytes, toByteArray(netOutputStream));
|
|
|
|
netOutputStream = createNetOutputStream();
|
|
netOutputStream.write(bytes);
|
|
|
|
assertArrayEquals(bytes, toByteArray(netOutputStream));
|
|
}
|
|
|
|
@Test
|
|
void write_offset() throws IOException {
|
|
byte[] bytes = new byte[128];
|
|
random.nextBytes(bytes);
|
|
NetOutputStream netOutputStream = createNetOutputStream();
|
|
netOutputStream.write(bytes, 3, 11);
|
|
|
|
byte[] actualBytes = new byte[11];
|
|
System.arraycopy(toByteArray(netOutputStream), 0, actualBytes, 0, 11);
|
|
|
|
byte[] expectedBytes = new byte[11];
|
|
System.arraycopy(bytes, 3, expectedBytes, 0, 11);
|
|
|
|
assertArrayEquals(expectedBytes, actualBytes);
|
|
}
|
|
|
|
private NetOutputStream createNetOutputStream() {
|
|
return new ByteArrayNetOutputStream();
|
|
}
|
|
|
|
private byte[] toByteArray(NetOutputStream netOutputStream) {
|
|
return ((ByteArrayNetOutputStream) netOutputStream).toByteArray();
|
|
}
|
|
|
|
private static Stream<Arguments> paramsWriteBoolean() {
|
|
return Stream.of(
|
|
Arguments.of(false, (byte) 0x00),
|
|
Arguments.of(true, (byte) 0x01)
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsWriteByte() {
|
|
byte b = Integer.valueOf(random.nextInt()).byteValue();
|
|
|
|
return Stream.of(
|
|
Arguments.of(b, b),
|
|
Arguments.of((byte) 128, (byte) -128)
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsWriteString() {
|
|
return Stream.of(
|
|
Arguments.of(""),
|
|
Arguments.of("Latin"),
|
|
Arguments.of("Кириллица"),
|
|
Arguments.of("العربية"),
|
|
Arguments.of("ﬦﬣﬡ"), // Алфавитные формы представления
|
|
Arguments.of("\uD800\uDD07") // Эгейские цифры, [один]
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsWriteVarInt() {
|
|
return Stream.of(
|
|
Arguments.of(120, new byte[]{ 0x78 }),
|
|
Arguments.of(12000, new byte[]{ (byte) 0xE0, 0x5D }),
|
|
Arguments.of(120000, new byte[]{ (byte) 0xC0, (byte) 0xA9, 0x07 }),
|
|
Arguments.of(120000000, new byte[]{ (byte) 0x80, (byte) 0x9C, (byte) 0x9C, (byte) 0x39 }),
|
|
Arguments.of(1200000000, new byte[]{ (byte) 0x80, (byte) 0x98, (byte) 0x9A, (byte) 0xBC, 0x04 })
|
|
);
|
|
}
|
|
|
|
private static Stream<Arguments> paramsWriteVarLong() {
|
|
return Stream.of(
|
|
Arguments.of(
|
|
12_000_000_000L,
|
|
new byte[]{ (byte) 0x80, (byte) 0xF0, (byte) 0x85, (byte) 0xDA, 0x2C }),
|
|
Arguments.of(
|
|
120_000_000_000L,
|
|
new byte[]{ (byte) 0x80, (byte) 0xE0, (byte) 0xBA, (byte) 0x84, (byte) 0xBF, 0x03 }),
|
|
Arguments.of(
|
|
12_000_000_000_000L,
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xF3, (byte) 0xBD, (byte) 0x9F, (byte) 0xDD,
|
|
0x02 }),
|
|
Arguments.of(
|
|
1_200_000_000_000_000L,
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xEC, (byte) 0xAD, (byte) 0xCC, (byte) 0xEC,
|
|
(byte) 0x90, 0x02}),
|
|
Arguments.of(
|
|
120_000_000_000_000_000L,
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0xB0, (byte) 0xE8, (byte) 0xD3, (byte) 0xEB,
|
|
(byte) 0x94, (byte) 0xD5, 0x01 }),
|
|
Arguments.of(
|
|
Long.MIN_VALUE,
|
|
new byte[]{ (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80,
|
|
(byte) 0x80, (byte) 0x80, (byte) 0x80, 0x01 })
|
|
);
|
|
}
|
|
} |