diff --git a/build.gradle b/build.gradle index 1707fd5..7958c21 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ group = 'mc-project' version = '0.0-SNAPSHOT' apply plugin: 'java' +apply plugin: 'jacoco' repositories { mavenLocal() @@ -15,18 +16,30 @@ compileJava { } ext { - slf4j_version = '1.7.25' - lombok_version = '1.18.2' + slf4j_version = '1.7.25' + lombok_version = '1.18.2' + junit_version = '5.3.1' } dependencies { /* LOGGER */ implementation (group: 'org.slf4j', name: 'slf4j-api', version: slf4j_version) - /* COMPONENTS */ - /* LOMBOK */ annotationProcessor (group: 'org.projectlombok', name: 'lombok', version: lombok_version) compileOnly (group: 'org.projectlombok', name: 'lombok', version: lombok_version) + + /* TESTING */ + testImplementation (group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junit_version) + testImplementation (group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: junit_version) + testRuntimeOnly (group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junit_version) + testImplementation (group: 'org.apache.commons', name: 'commons-lang3', version: '3.9') } +test { + useJUnitPlatform() +} + +jacoco { + toolVersion = '0.8.3' +} diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..48a65c1 --- /dev/null +++ b/lombok.config @@ -0,0 +1,2 @@ +# Добавить runtime аннотацию @lombok.Generated ко всем генерируемым методам "ломбока" +lombok.addLombokGeneratedAnnotation = true \ No newline at end of file diff --git a/src/test/java/mc/nbt/io/NbtInputStreamTest.java b/src/test/java/mc/nbt/io/NbtInputStreamTest.java new file mode 100644 index 0000000..a7b2b3f --- /dev/null +++ b/src/test/java/mc/nbt/io/NbtInputStreamTest.java @@ -0,0 +1,203 @@ +package mc.nbt.io; + +import mc.nbt.TypeTag; +import mc.nbt.tag.*; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +//TODO необходимо добавить тесты для INT_ARRAY и LONG_ARRAY +class NbtInputStreamTest { + + @Test + void testSimple() throws IOException { + InputStream stream = NbtInputStreamTest.class.getResourceAsStream("/hello_world.nbt"); + assertNotNull(stream); + + NbtInputStream nbtInputStream = new NbtInputStream(stream); + Tag tag = nbtInputStream.readTag(); + assertNotNull(tag); + assertEquals(TypeTag.COMPOUND, tag.getType()); + + TagCompound tagCompound = tag.asTagCompound(); + assertEquals("hello world", tagCompound.getName()); + assertEquals(1, tagCompound.getValue().size()); + + tag = tagCompound.getValue().get(0); + assertEquals(TypeTag.STRING, tag.getType()); + + TagString tagString = tag.asTagString(); + assertEquals("name", tagString.getName()); + assertEquals("Bananrama", tagString.getValue()); + } + + @Test + void testGZipped() throws IOException { + InputStream stream = NbtInputStreamTest.class.getResourceAsStream("/bigtest.nbt"); + assertNotNull(stream); + + NbtInputStream nbtInputStream = new NbtInputStream(stream, true); + Tag tag = nbtInputStream.readTag(); + assertNotNull(tag); + assertEquals(TypeTag.COMPOUND, tag.getType()); + + TagCompound tagCompound = tag.asTagCompound(); + assertEquals("Level", tagCompound.getName()); + assertEquals(11, tagCompound.getValue().size()); + + tagCompound.getValue().forEach(tag1 -> { + switch (tag1.getType()) { + case BYTE: testTagByte(tag1.asTagByte()); break; + case SHORT: testTagShort(tag1.asTagShort()); break; + case INT: testTagInt(tag1.asTagInt()); break; + case LONG: testTagLong(tag1.asTagLong()); break; + case FLOAT: testTagFloat(tag1.asTagFloat()); break; + case DOUBLE: testTagDouble(tag1.asTagDouble()); break; + case BYTE_ARRAY: testTagByteArray(tag1.asTagByteArray()); break; + case STRING: testTagString(tag1.asTagString()); break; + case LIST: testTagList(tag1.asTagList()); break; + case COMPOUND: testTagCompound(tag1.asTagCompound()); break; + } + }); + } + + private void testTagByte(TagByte tag) { + assertEquals("byteTest", tag.getName()); + assertEquals(Byte.MAX_VALUE, tag.getValue()); + } + + private void testTagShort(TagShort tag) { + assertEquals("shortTest", tag.getName()); + assertEquals(Short.MAX_VALUE, tag.getValue()); + } + + private void testTagInt(TagInt tag) { + assertEquals("intTest", tag.getName()); + assertEquals(Integer.MAX_VALUE, tag.getValue()); + } + + private void testTagLong(TagLong tag) { + assertEquals("longTest", tag.getName()); + assertEquals(Long.MAX_VALUE, tag.getValue()); + } + + private void testTagFloat(TagFloat tag) { + assertEquals("floatTest", tag.getName()); + assertEquals(0.49823147058486938f, tag.getValue()); + } + + private void testTagDouble(TagDouble tag) { + assertEquals("doubleTest", tag.getName()); + assertEquals(0.49312871321823148d, tag.getValue()); + } + + private void testTagByteArray(TagByteArray tag) { + assertEquals("byteArrayTest " + + "(the first 1000 values of (n*n*255+n*7)%100, " + + "starting with n=0 (0, 62, 34, 16, 8, ...))", tag.getName()); + assertEquals(1000, tag.getValue().length); + + for (int n = 0; n < tag.getValue().length; n++) { + assertEquals((n * n * 255 + n * 7) % 100, tag.getValue()[n]); + } + } + + private void testTagString(TagString tag) { + assertEquals("stringTest", tag.getName()); + assertEquals("HELLO WORLD THIS IS A TEST STRING \305\304\326!", tag.getValue()); + } + + private void testTagList(TagList tag) { + if (tag.getName().equals("listTest (long)")) { + testTagListLong(tag); + } else if (tag.getName().equals("listTest (compound)")) { + testTagListCompound(tag); + } else { + fail("Unknown TagList(name=" + tag.getName() + ")"); + } + } + + private void testTagListLong(TagList tag) { + assertEquals(TypeTag.LONG, tag.getTypeList()); + assertEquals(5, tag.getValue().size()); + + Iterator iterator = tag.getValue().iterator(); + for(int n = 11; n <= 15 && iterator.hasNext(); n++) { + assertEquals(n, iterator.next().asTagLong().getValue()); + } + } + + private void testTagListCompound(TagList tag) { + assertEquals(TypeTag.COMPOUND, tag.getTypeList()); + assertEquals(2, tag.getValue().size()); + + { + TagCompound tagCompound = tag.getValue().get(0).asTagCompound(); + assertNull(tagCompound.getName()); + assertEquals(2, tagCompound.getValue().size()); + + TagString tagString = tagCompound.getValue().get(0).asTagString(); + assertEquals("name", tagString.getName()); + assertEquals("Compound tag #0", tagString.getValue()); + + TagLong tagLong = tagCompound.getValue().get(1).asTagLong(); + assertEquals("created-on", tagLong.getName()); + assertEquals(1264099775885L, tagLong.getValue()); + } + + { + TagCompound tagCompound = tag.getValue().get(1).asTagCompound(); + assertNull(tagCompound.getName()); + assertEquals(2, tagCompound.getValue().size()); + + TagString tagString = tagCompound.getValue().get(0).asTagString(); + assertEquals("name", tagString.getName()); + assertEquals("Compound tag #1", tagString.getValue()); + + TagLong tagLong = tagCompound.getValue().get(1).asTagLong(); + assertEquals("created-on", tagLong.getName()); + assertEquals(1264099775885L, tagLong.getValue()); + } + } + + private void testTagCompound(TagCompound tag) { + assertEquals("nested compound test", tag.getName()); + assertEquals(2, tag.getValue().size()); + + { + TagCompound tagCompound = tag.getValue().get(0).asTagCompound(); + assertEquals("ham", tagCompound.getName()); + assertEquals(2, tagCompound.getValue().size()); + + { + TagString tagString = tagCompound.getValue().get(0).asTagString(); + assertEquals("name", tagString.getName()); + assertEquals("Hampus", tagString.getValue()); + + TagFloat tagFloat = tagCompound.getValue().get(1).asTagFloat(); + assertEquals("value", tagFloat.getName()); + assertEquals(0.75f, tagFloat.getValue()); + } + } + + { + TagCompound tagCompound = tag.getValue().get(1).asTagCompound(); + assertEquals("egg", tagCompound.getName()); + assertEquals(2, tagCompound.getValue().size()); + + { + TagString tagString = tagCompound.getValue().get(0).asTagString(); + assertEquals("name", tagString.getName()); + assertEquals("Eggbert", tagString.getValue()); + + TagFloat tagFloat = tagCompound.getValue().get(1).asTagFloat(); + assertEquals("value", tagFloat.getName()); + assertEquals(0.5f, tagFloat.getValue()); + } + } + } +} diff --git a/src/test/java/mc/nbt/io/NbtOutputStreamCompressedTest.java b/src/test/java/mc/nbt/io/NbtOutputStreamCompressedTest.java new file mode 100644 index 0000000..02a3d34 --- /dev/null +++ b/src/test/java/mc/nbt/io/NbtOutputStreamCompressedTest.java @@ -0,0 +1,33 @@ +package mc.nbt.io; + +import mc.nbt.TypeTag; +import mc.nbt.tag.Tag; +import mc.nbt.tag.TagLong; +import org.apache.commons.lang3.RandomUtils; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class NbtOutputStreamCompressedTest { + + @Test + void testWriteCompressed() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + NbtOutputStream nbtOutputStream = new NbtOutputStream(baos, true); + + TagLong tagLong = new TagLong("Test compressed stream", RandomUtils.nextLong()); + nbtOutputStream.writeTag(tagLong); + nbtOutputStream.close(); + + NbtInputStream nbtInputStream = new NbtInputStream(new ByteArrayInputStream(baos.toByteArray()), true); + Tag tag = nbtInputStream.readTag(); + + assertEquals(TypeTag.LONG, tag.getType()); + assertEquals(tagLong.getName(), tag.getName()); + assertEquals(tagLong.getValue(), tag.asTagLong().getValue()); + } +} diff --git a/src/test/java/mc/nbt/io/NbtOutputStreamTest.java b/src/test/java/mc/nbt/io/NbtOutputStreamTest.java new file mode 100644 index 0000000..f6d3348 --- /dev/null +++ b/src/test/java/mc/nbt/io/NbtOutputStreamTest.java @@ -0,0 +1,331 @@ +package mc.nbt.io; + +import mc.nbt.TypeTag; +import mc.nbt.tag.*; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class NbtOutputStreamTest { + + private ByteArrayOutputStream baos; + private NbtOutputStream nbtOutputStream; + + @BeforeEach + void before() throws IOException { + baos = new ByteArrayOutputStream(); + nbtOutputStream = new NbtOutputStream(baos); + } + + @Test + void testWriteTagEnd() throws IOException { + nbtOutputStream.writeTag(new TagEnd()); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.END, tag.getType()); + assertNull(tag.getName()); + } + + private static Stream streamOfTagByte() { + final byte value = RandomUtils.nextBytes(1)[0]; + + return Stream.of( + Arguments.of(new TagByte(value)), + Arguments.of(new TagByte(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagByte") + void testWriteTagByte(TagByte tagByte) throws IOException { + nbtOutputStream.writeTag(tagByte); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.BYTE, tag.getType()); + assertEquals(tagByte.getValue(), tag.asTagByte().getValue()); + assertName(tagByte, tag); + } + + private static Stream streamOfTagShort() { + final short value = (short) RandomUtils.nextInt(0, Short.MAX_VALUE); + + return Stream.of( + Arguments.of(new TagShort(value)), + Arguments.of(new TagShort(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagShort") + void testWriteTagShort(TagShort tagShort) throws IOException { + nbtOutputStream.writeTag(tagShort); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.SHORT, tag.getType()); + assertEquals(tagShort.getValue(), tag.asTagShort().getValue()); + assertName(tagShort, tag); + } + + private static Stream streamOfTagInt() { + final int value = RandomUtils.nextInt(); + + return Stream.of( + Arguments.of(new TagInt(value)), + Arguments.of(new TagInt(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagInt") + void testWriteTagInt(TagInt tagInt) throws IOException { + nbtOutputStream.writeTag(tagInt); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.INT, tag.getType()); + assertEquals(tagInt.getValue(), tag.asTagInt().getValue()); + assertName(tagInt, tag); + } + + private static Stream streamOfTagLong() { + final long value = RandomUtils.nextLong(); + + return Stream.of( + Arguments.of(new TagLong(value)), + Arguments.of(new TagLong(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagLong") + void testWriteTagLong(TagLong tagLong) throws IOException { + nbtOutputStream.writeTag(tagLong); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.LONG, tag.getType()); + assertEquals(tagLong.getValue(), tag.asTagLong().getValue()); + assertName(tagLong, tag); + } + + private static Stream streamOfTagFloat() { + final float value = RandomUtils.nextFloat(); + + return Stream.of( + Arguments.of(new TagFloat(value)), + Arguments.of(new TagFloat(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagFloat") + void testWriteTagFloat(TagFloat tagFloat) throws IOException { + nbtOutputStream.writeTag(tagFloat); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.FLOAT, tag.getType()); + assertEquals(tagFloat.getValue(), tag.asTagFloat().getValue()); + assertName(tagFloat, tag); + } + + private static Stream streamOfTagDouble() { + final double value = RandomUtils.nextDouble(); + + return Stream.of( + Arguments.of(new TagDouble(value)), + Arguments.of(new TagDouble(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagDouble") + void testWriteTagDouble(TagDouble tagDouble) throws IOException { + nbtOutputStream.writeTag(tagDouble); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.DOUBLE, tag.getType()); + assertEquals(tagDouble.getValue(), tag.asTagDouble().getValue()); + assertName(tagDouble, tag); + } + + private static Stream streamOfTagByteArray() { + final byte[] value = RandomUtils.nextBytes(RandomUtils.nextInt(1, 1000)); + + return Stream.of( + Arguments.of(new TagByteArray(value)), + Arguments.of(new TagByteArray(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagByteArray") + void testWriteTagByteArray(TagByteArray tagByteArray) throws IOException { + nbtOutputStream.writeTag(tagByteArray); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.BYTE_ARRAY, tag.getType()); + assertArrayEquals(tagByteArray.getValue(), tag.asTagByteArray().getValue()); + assertName(tagByteArray, tag); + } + + private static Stream streamOfTagString() { + final String value = randomString(); + + return Stream.of( + Arguments.of(new TagString(value)), + Arguments.of(new TagString(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagString") + void testWriteTagString(TagString tagString) throws IOException { + nbtOutputStream.writeTag(tagString); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.STRING, tag.getType()); + assertEquals(tagString.getValue(), tag.asTagString().getValue()); + assertName(tagString, tag); + } + + private static Stream streamOfTagList() { + final List value = new ArrayList<>(); + value.add(new TagLong("TestName", RandomUtils.nextLong())); + value.add(new TagLong(RandomUtils.nextLong())); + value.add(new TagLong(RandomUtils.nextLong())); + value.add(new TagLong(RandomUtils.nextLong())); + + return Stream.of( + Arguments.of(new TagList(value)), + Arguments.of(new TagList(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagList") + void testWriteTagList(TagList tagList) throws IOException { + nbtOutputStream.writeTag(tagList); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.LIST, tag.getType()); + assertEquals(tagList.getValue().size(), tag.asTagList().getValue().size()); + assertEquals(tagList.getTypeList(), tag.asTagList().getTypeList()); + assertName(tagList, tag); + + for (int i = 0; i < tagList.getValue().size(); i++) { + TagLong tagLong1 = tagList.getValue().get(i).asTagLong(); + TagLong tagLong2 = tag.asTagList().getValue().get(i).asTagLong(); + + assertNull(tagLong2.getName()); + assertEquals(tagLong1.getValue(), tagLong2.getValue()); + } + } + + private static Stream streamOfTagCompound() { + final List value = new ArrayList<>(); + value.add(new TagLong("TestName1", RandomUtils.nextLong())); + value.add(new TagLong(RandomUtils.nextLong())); + value.add(new TagLong("TestName3",RandomUtils.nextLong())); + value.add(new TagLong(RandomUtils.nextLong())); + + return Stream.of( + Arguments.of(new TagCompound(value)), + Arguments.of(new TagCompound(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagCompound") + void testWriteTagCompound(TagCompound tagCompound) throws IOException { + nbtOutputStream.writeTag(tagCompound); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.COMPOUND, tag.getType()); + assertEquals(tagCompound.getValue().size(), tag.asTagCompound().getValue().size()); + assertName(tagCompound, tag); + + for (int i = 0; i < tagCompound.getValue().size(); i++) { + TagLong tagLong1 = tagCompound.getValue().get(i).asTagLong(); + TagLong tagLong2 = tag.asTagCompound().getValue().get(i).asTagLong(); + + assertNotNull(tagLong2.getName()); + assertName(tagLong1, tagLong2); + assertEquals(tagLong1.getValue(), tagLong2.getValue()); + } + } + + private static Stream streamOfTagIntArray() { + final int[] value = new int[RandomUtils.nextInt(1, 1000)]; + + for (int i = 0; i < value.length; i++) { + value[i] = RandomUtils.nextInt(); + } + + return Stream.of( + Arguments.of(new TagIntArray(value)), + Arguments.of(new TagIntArray(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagIntArray") + void testWriteTagIntArray(TagIntArray tagIntArray) throws IOException { + nbtOutputStream.writeTag(tagIntArray); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.INT_ARRAY, tag.getType()); + assertArrayEquals(tagIntArray.getValue(), tag.asTagIntArray().getValue()); + assertName(tagIntArray, tag); + } + + private static Stream streamOfTagLongArray() { + final long[] value = new long[RandomUtils.nextInt(1, 1000)]; + + for (int i = 0; i < value.length; i++) { + value[i] = RandomUtils.nextLong(); + } + + return Stream.of( + Arguments.of(new TagLongArray(value)), + Arguments.of(new TagLongArray(randomString(), value)) + ); + } + + @ParameterizedTest + @MethodSource("streamOfTagLongArray") + void testWriteTagLongArray(TagLongArray tagLongArray) throws IOException { + nbtOutputStream.writeTag(tagLongArray); + + Tag tag = createNbtInputStream().readTag(); + assertEquals(TypeTag.LONG_ARRAY, tag.getType()); + assertArrayEquals(tagLongArray.getValue(), tag.asTagLongArray().getValue()); + assertName(tagLongArray, tag); + } + + private void assertName(Tag expectedTag, Tag actualTag) { + if (expectedTag.getName() == null) { + assertTrue(actualTag.getName().isEmpty()); + } else { + assertEquals(expectedTag.getName(), actualTag.getName()); + } + } + + private static String randomString() { + return RandomStringUtils.randomAscii(RandomUtils.nextInt(1, Short.MAX_VALUE)); + } + + private NbtInputStream createNbtInputStream() throws IOException { + return new NbtInputStream(new ByteArrayInputStream(baos.toByteArray())); + } +} \ No newline at end of file diff --git a/src/test/java/mc/nbt/tag/TagEndTest.java b/src/test/java/mc/nbt/tag/TagEndTest.java new file mode 100644 index 0000000..c40a3d5 --- /dev/null +++ b/src/test/java/mc/nbt/tag/TagEndTest.java @@ -0,0 +1,30 @@ +package mc.nbt.tag; + +import mc.nbt.TypeTag; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class TagEndTest { + + @Test + void testUnsupportSetName() { + TagEnd tagEnd = new TagEnd(); + + assertThrows(UnsupportedOperationException.class, () -> tagEnd.setName("any")); + } + + @Test + void testGetName() { + TagEnd tagEnd = new TagEnd(); + + assertNull(tagEnd.getName()); + } + + @Test + void testGetType() { + TagEnd tagEnd = new TagEnd(); + + assertEquals(TypeTag.END, tagEnd.getType()); + } +} diff --git a/src/test/resources/bigtest.nbt b/src/test/resources/bigtest.nbt new file mode 100644 index 0000000..dc3769b Binary files /dev/null and b/src/test/resources/bigtest.nbt differ diff --git a/src/test/resources/hello_world.nbt b/src/test/resources/hello_world.nbt new file mode 100644 index 0000000..f3f5e21 Binary files /dev/null and b/src/test/resources/hello_world.nbt differ