blob: eaf5f0bbe3f835cc75d59d7abc3508e9ae6a911d [file] [log] [blame] [raw]
package net.querz.nbt.test;
import junit.framework.TestCase;
import net.querz.nbt.*;
import net.querz.nbt.custom.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import static net.querz.nbt.test.TestUtil.*;
public class NBTTest extends TestCase {
public void testByteTag() {
ByteTag t = new ByteTag(Byte.MAX_VALUE);
assertEquals(Byte.MAX_VALUE, t.asByte());
assertEquals(Byte.MAX_VALUE, t.asShort());
assertEquals(Byte.MAX_VALUE, t.asInt());
assertEquals(Byte.MAX_VALUE, t.asLong());
assertEquals(1, t.getID());
assertEquals(Byte.MAX_VALUE + "b", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Byte.MAX_VALUE + "}", t.toString());
ByteTag t2 = new ByteTag(Byte.MAX_VALUE);
assertTrue(t.equals(t2));
ByteTag t3 = new ByteTag(Byte.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
ByteTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{1, 0, 0, 127}, data));
ByteTag tt = (ByteTag) deserialize(data);
assertTrue(t.equals(tt));
assertFalse(new ByteTag((byte) 0).asBoolean());
assertFalse(new ByteTag(Byte.MIN_VALUE).asBoolean());
assertTrue(new ByteTag((byte) 1).asBoolean());
assertTrue(new ByteTag(Byte.MAX_VALUE).asBoolean());
}
public void testShortTag() {
ShortTag t = new ShortTag(Short.MAX_VALUE);
assertEquals(Short.MAX_VALUE, t.asShort());
assertEquals(Short.MAX_VALUE, t.asInt());
assertEquals(Short.MAX_VALUE, t.asLong());
assertEquals(2, t.getID());
assertEquals(Short.MAX_VALUE + "s", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Short.MAX_VALUE + "}", t.toString());
ShortTag t2 = new ShortTag(Short.MAX_VALUE);
assertTrue(t.equals(t2));
ShortTag t3 = new ShortTag(Short.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
ShortTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{2, 0, 0, 127, -1}, data));
ShortTag tt = (ShortTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testIntTag() {
IntTag t = new IntTag(Integer.MAX_VALUE);
assertEquals(Integer.MAX_VALUE, t.asInt());
assertEquals(Integer.MAX_VALUE, t.asLong());
assertEquals(3, t.getID());
assertEquals(Integer.MAX_VALUE + "", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Integer.MAX_VALUE + "}", t.toString());
IntTag t2 = new IntTag(Integer.MAX_VALUE);
assertTrue(t.equals(t2));
IntTag t3 = new IntTag(Integer.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
IntTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{3, 0, 0, 127, -1, -1, -1}, data));
IntTag tt = (IntTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testLongTag() {
LongTag t = new LongTag(Long.MAX_VALUE);
assertEquals(Long.MAX_VALUE, t.asLong());
assertEquals(4, t.getID());
assertEquals(Long.MAX_VALUE + "l", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Long.MAX_VALUE + "}", t.toString());
LongTag t2 = new LongTag(Long.MAX_VALUE);
assertTrue(t.equals(t2));
LongTag t3 = new LongTag(Long.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
LongTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{4, 0, 0, 127, -1, -1, -1, -1, -1, -1, -1}, data));
LongTag tt = (LongTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testFloatTag() {
FloatTag t = new FloatTag(Float.MAX_VALUE);
assertEquals(Float.MAX_VALUE, t.asFloat());
assertEquals(5, t.getID());
assertEquals(Float.MAX_VALUE + "f", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Float.MAX_VALUE + "}", t.toString());
FloatTag t2 = new FloatTag(Float.MAX_VALUE);
assertTrue(t.equals(t2));
FloatTag t3 = new FloatTag(Float.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
FloatTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{5, 0, 0, 127, 127, -1, -1}, data));
FloatTag tt = (FloatTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testDoubleTag() {
DoubleTag t = new DoubleTag(Double.MAX_VALUE);
assertEquals(Double.MAX_VALUE, t.asDouble());
assertEquals(6, t.getID());
assertEquals(Double.MAX_VALUE + "d", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":" + Double.MAX_VALUE + "}", t.toString());
DoubleTag t2 = new DoubleTag(Double.MAX_VALUE);
assertTrue(t.equals(t2));
DoubleTag t3 = new DoubleTag(Double.MIN_VALUE);
assertFalse(t.equals(t3));
//test cloning
DoubleTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{6, 0, 0, 127, -17, -1, -1, -1, -1, -1, -1}, data));
DoubleTag tt = (DoubleTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testStringTag() {
StringTag t = new StringTag("foo");
assertEquals("foo", t.getValue());
assertEquals(8, t.getID());
assertEquals("foo", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":\"foo\"}", t.toString());
StringTag t2 = new StringTag("foo");
assertTrue(t.equals(t2));
StringTag t3 = new StringTag("something else");
assertFalse(t.equals(t3));
//test cloning
StringTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{8, 0, 0, 0, 3, 102, 111, 111}, data));
StringTag tt = (StringTag) deserialize(data);
assertTrue(t.equals(tt));
//test string escaping
StringTag allValue = new StringTag("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_-+");
assertEquals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_-+", allValue.toTagString());
StringTag escapeValue = new StringTag("öäü");
assertEquals("\"öäü\"", escapeValue.toTagString());
StringTag escapeSpecialChars = new StringTag("\\\n\r\t\"");
assertEquals("\"\\\\\\n\\r\\t\\\"\"", escapeSpecialChars.toTagString());
StringTag escapeEmpty = new StringTag("");
assertEquals("\"\"", escapeEmpty.toTagString());
//no null values allowed
assertThrowsException(() -> new StringTag().setValue(null), NullPointerException.class);
}
public void testByteArrayTag() {
ByteArrayTag t = new ByteArrayTag(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE});
assertTrue(Arrays.equals(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE}, t.getValue()));
assertEquals(7, t.getID());
assertEquals("[B;-128b,0b,127b]", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":[-128,0,127]}", t.toString());
ByteArrayTag t2 = new ByteArrayTag(new byte[]{Byte.MIN_VALUE, 0, Byte.MAX_VALUE});
assertTrue(t.equals(t2));
ByteArrayTag t3 = new ByteArrayTag(new byte[]{Byte.MAX_VALUE, 0, Byte.MIN_VALUE});
assertFalse(t.equals(t3));
//test cloning
ByteArrayTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
assertFalse(t.getValue() == tc.getValue());
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{7, 0, 0, 0, 0, 0, 3, -128, 0, 127}, data));
ByteArrayTag tt = (ByteArrayTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testIntArrayTag() {
IntArrayTag t = new IntArrayTag(new int[]{Integer.MIN_VALUE, 0, Integer.MAX_VALUE});
assertTrue(Arrays.equals(new int[]{Integer.MIN_VALUE, 0, Integer.MAX_VALUE}, t.getValue()));
assertEquals(11, t.getID());
assertEquals("[I;-2147483648,0,2147483647]", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":[-2147483648,0,2147483647]}", t.toString());
IntArrayTag t2 = new IntArrayTag(new int[]{Integer.MIN_VALUE, 0, Integer.MAX_VALUE});
assertTrue(t.equals(t2));
IntArrayTag t3 = new IntArrayTag(new int[]{Integer.MAX_VALUE, 0, Integer.MIN_VALUE});
assertFalse(t.equals(t3));
//test cloning
IntArrayTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
assertFalse(t.getValue() == tc.getValue());
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{11, 0, 0, 0, 0, 0, 3, -128, 0, 0, 0, 0, 0, 0, 0, 127, -1, -1, -1}, data));
IntArrayTag tt = (IntArrayTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testLongArrayTag() {
LongArrayTag t = new LongArrayTag(new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE});
assertTrue(Arrays.equals(new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE}, t.getValue()));
assertEquals(12, t.getID());
assertEquals("[L;-9223372036854775808l,0l,9223372036854775807l]", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":[-9223372036854775808,0,9223372036854775807]}", t.toString());
LongArrayTag t2 = new LongArrayTag(new long[]{Long.MIN_VALUE, 0, Long.MAX_VALUE});
assertTrue(t.equals(t2));
LongArrayTag t3 = new LongArrayTag(new long[]{Long.MAX_VALUE, 0, Long.MIN_VALUE});
assertFalse(t.equals(t3));
//test cloning
LongArrayTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
assertFalse(t.getValue() == tc.getValue());
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{12, 0, 0, 0, 0, 0, 3, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, -1, -1, -1, -1, -1, -1, -1}, data));
LongArrayTag tt = (LongArrayTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testListTag() {
ListTag<ByteTag> bl = new ListTag<>();
bl.add(new ByteTag(Byte.MIN_VALUE));
bl.add(new ByteTag((byte) 0));
bl.add(new ByteTag(Byte.MAX_VALUE));
assertTrue(3 == bl.size());
assertEquals(Byte.MIN_VALUE, bl.get(0).asByte());
assertEquals(0, bl.get(1).asByte());
assertEquals(Byte.MAX_VALUE, bl.get(2).asByte());
assertEquals("[-128b,0b,127b]", bl.toTagString());
assertEquals("{\"type\":\"ListTag\"," +
"\"value\":{" +
"\"type\":\"ByteTag\"," +
"\"list\":[" +
"{\"type\":\"ByteTag\",\"value\":-128}," +
"{\"type\":\"ByteTag\",\"value\":0}," +
"{\"type\":\"ByteTag\",\"value\":127}]}}", bl.toString());
//test equality
ListTag<ByteTag> bl2 = new ListTag<>();
bl2.addByte(Byte.MIN_VALUE);
bl2.addByte((byte) 0);
bl2.addByte(Byte.MAX_VALUE);
assertTrue(bl.equals(bl2));
ListTag<ByteTag> bl3 = new ListTag<>();
bl2.addByte(Byte.MAX_VALUE);
bl2.addByte((byte) 0);
bl2.addByte(Byte.MIN_VALUE);
assertFalse(bl.equals(bl3));
ListTag<ByteTag> bl4 = new ListTag<>();
bl2.addByte(Byte.MIN_VALUE);
bl2.addByte((byte) 0);
assertFalse(bl.equals(bl4));
//test cloning
ListTag<ByteTag> tc = bl.clone();
assertTrue(bl.equals(tc));
assertFalse(bl == tc);
assertFalse(invokeGetValue(bl) == invokeGetValue(tc));
//test serialization / deserialization
byte[] data = serialize(bl);
assertTrue(Arrays.equals(new byte[]{9, 0, 0, 1, 0, 0, 0, 3, -128, 0, 127}, data));
ListTag<?> tt = (ListTag<?>) deserialize(data);
assertNotNull(tt);
ListTag<ByteTag> ttt = tt.asByteTagList();
assertTrue(bl.equals(ttt));
//test casting and type consistency
ListTag<ByteTag> b = new ListTag<>();
b.addByte((byte) 123);
assertThrowsException(() -> b.addShort((short) 123), IllegalArgumentException.class);
assertThrowsException(b::asShortTagList, ClassCastException.class);
assertEquals(ByteTag.class, b.getTypeClass());
assertEquals(1, b.getTypeID());
b.clear();
assertThrowsNoException(() -> b.addShort((short) 123));
assertThrowsException(() -> b.addByte((byte) 123), IllegalArgumentException.class);
assertThrowsNoException(b::asShortTagList);
assertThrowsException(b::asByteTagList, ClassCastException.class);
assertThrowsNoException(() -> b.asTypedList(ShortTag.class));
assertThrowsException(() -> b.asTypedList(ByteTag.class), ClassCastException.class);
b.remove(0);
assertEquals(EndTag.class, b.getTypeClass());
//test compareTo
ListTag<IntTag> li = new ListTag<>();
li.addInt(1);
li.addInt(2);
ListTag<IntTag> lo = new ListTag<>();
lo.addInt(3);
lo.addInt(4);
assertEquals(0, li.compareTo(lo));
lo.addInt(5);
assertEquals(-1, li.compareTo(lo));
lo.remove(2);
lo.remove(1);
assertEquals(1, li.compareTo(lo));
//test max depth
ListTag<ListTag<?>> root = new ListTag<>();
ListTag<ListTag<?>> rec = root;
for (int i = 0; i < Tag.MAX_DEPTH + 1; i++) {
ListTag<ListTag<?>> l = new ListTag<>();
rec.add(l);
rec = l;
}
assertThrowsException(() -> serialize(root), MaxDepthReachedException.class);
assertThrowsException(() -> deserializeFromFile("max_depth_reached.dat"), MaxDepthReachedException.class);
assertThrowsException(root::toString, MaxDepthReachedException.class);
assertThrowsException(root::toTagString, MaxDepthReachedException.class);
assertThrowsException(() -> root.valueToString(-1), IllegalArgumentException.class);
assertThrowsException(() -> root.valueToTagString(-1), IllegalArgumentException.class);
//test recursion
ListTag<ListTag<?>> recursive = new ListTag<>();
recursive.add(recursive);
assertThrowsException(() -> serialize(recursive), MaxDepthReachedException.class);
assertThrowsException(recursive::toString, MaxDepthReachedException.class);
assertThrowsException(recursive::toTagString, MaxDepthReachedException.class);
}
public void testCompoundTag() {
CompoundTag ct = new CompoundTag();
invokeSetValue(ct, new LinkedHashMap<>());
ct.put("b", new ByteTag(Byte.MAX_VALUE));
ct.put("str", new StringTag("foo"));
ct.put("list", new ListTag<>());
ct.getListTag("list").addByte((byte) 123);
assertTrue(3 == ct.size());
assertTrue(ct.containsKey("b"));
assertTrue(ct.containsKey("str"));
assertTrue(ct.containsKey("list"));
assertFalse(ct.containsKey("invalid"));
assertEquals("{b:127b,str:foo,list:[123b]}", ct.toTagString());
assertEquals("{\"type\":\"CompoundTag\"," +
"\"value\":{" +
"\"b\":{\"type\":\"ByteTag\",\"value\":127}," +
"\"str\":{\"type\":\"StringTag\",\"value\":\"foo\"}," +
"\"list\":{\"type\":\"ListTag\"," +
"\"value\":{\"type\":\"ByteTag\",\"list\":[{\"type\":\"ByteTag\",\"value\":123}]}}}}", ct.toString());
//test equality
CompoundTag ct2 = new CompoundTag();
ct2.putByte("b", Byte.MAX_VALUE);
ct2.putString("str", "foo");
ct2.put("list", new ListTag<>());
ct2.getListTag("list").addByte((byte) 123);
assertTrue(ct.equals(ct2));
ct2.getListTag("list").asByteTagList().get(0).setValue((byte) 124);
assertFalse(ct.equals(ct2));
//test cloning
CompoundTag cl = ct.clone();
assertTrue(ct.equals(cl));
assertFalse(ct == cl);
assertFalse(ct.get("list") == cl.get("list"));
assertFalse(invokeGetValue(ct) == invokeGetValue(cl));
//test serialization / deserialization
byte[] data = serialize(ct);
assertTrue(Arrays.equals(new byte[]{10, 0, 0, 1, 0, 1, 98, 127, 8, 0, 3, 115, 116, 114, 0, 3, 102, 111, 111, 9, 0, 4, 108, 105, 115, 116, 1, 0, 0, 0, 1, 123, 0}, data));
CompoundTag tt = (CompoundTag) deserialize(data);
assertTrue(ct.equals(tt));
//casting
CompoundTag cc = new CompoundTag();
cc.putInt("one", 1);
assertThrowsException(() -> cc.getLong("one"), ClassCastException.class);
//test compareTo
CompoundTag ci = new CompoundTag();
ci.putInt("one", 1);
ci.putInt("two", 2);
CompoundTag co = new CompoundTag();
co.putInt("three", 3);
co.putInt("four", 4);
assertEquals(0, ci.compareTo(co));
co.putInt("five", 5);
assertEquals(-1, ci.compareTo(co));
co.remove("five");
co.remove("four");
assertEquals(1, ci.compareTo(co));
//test max depth
CompoundTag root = new CompoundTag();
CompoundTag rec = root;
for (int i = 0; i < Tag.MAX_DEPTH + 1; i++) {
CompoundTag c = new CompoundTag();
rec.put("c" + i, c);
rec = c;
}
assertThrowsException(() -> serialize(root), MaxDepthReachedException.class);
assertThrowsException(() -> deserializeFromFile("max_depth_reached.dat"), MaxDepthReachedException.class);
assertThrowsException(root::toString, MaxDepthReachedException.class);
assertThrowsException(root::toTagString, MaxDepthReachedException.class);
assertThrowsException(() -> root.valueToString(-1), IllegalArgumentException.class);
assertThrowsException(() -> root.valueToTagString(-1), IllegalArgumentException.class);
//test recursion
CompoundTag recursive = new CompoundTag();
recursive.put("recursive", recursive);
assertThrowsException(() -> serialize(recursive), MaxDepthReachedException.class);
assertThrowsException(recursive::toString, MaxDepthReachedException.class);
assertThrowsException(recursive::toTagString, MaxDepthReachedException.class);
//test entrySet setValue
CompoundTag e = new CompoundTag();
e.putInt("int", 123);
for (Map.Entry<String, Tag> en : e.entrySet()) {
assertThrowsException(() -> en.setValue(null), NullPointerException.class);
assertThrowsNoException(() -> en.setValue(new IntTag(321)));
}
assertEquals(1, e.size());
assertEquals(321, e.getInt("int"));
}
public void testCustomCharTag() {
CharTag.register();
CharTag t = new CharTag('a');
assertEquals('a', (char) t.getValue());
assertEquals(110, t.getID());
assertEquals("a", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":\"a\"}", t.toString());
CharTag t2 = new CharTag('a');
assertTrue(t.equals(t2));
CharTag t3 = new CharTag('b');
assertFalse(t.equals(t3));
//test cloning
CharTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{110, 0, 0, 0, 97}, data));
CharTag tt = (CharTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testCustomShortArrayTag() {
ShortArrayTag.register();
ShortArrayTag t = new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE});
assertTrue(Arrays.equals(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}, t.getValue()));
assertEquals(100, t.getID());
assertEquals("[S;-32768s,0s,32767s]", t.toTagString());
assertEquals("{\"type\":\"" + t.getClass().getSimpleName() + "\",\"value\":[-32768,0,32767]}", t.toString());
ShortArrayTag t2 = new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE});
assertTrue(t.equals(t2));
ShortArrayTag t3 = new ShortArrayTag(new short[]{Short.MAX_VALUE, 0, Short.MIN_VALUE});
assertFalse(t.equals(t3));
//test cloning
ShortArrayTag tc = t.clone();
assertTrue(t.equals(tc));
assertFalse(t == tc);
assertFalse(t.getValue() == tc.getValue());
//test serialization
byte[] data = serialize(t);
assertTrue(Arrays.equals(new byte[]{100, 0, 0, 0, 0, 0, 3, -128, 0, 0, 0, 127, -1}, data));
ShortArrayTag tt = (ShortArrayTag) deserialize(data);
assertTrue(t.equals(tt));
}
public void testCustomObjectTag() {
ObjectTag.register();
DummyObject d = new DummyObject();
ObjectTag<DummyObject> o = new ObjectTag<>(d);
assertEquals(90, o.getID());
assertEquals("{\"type\":\"ObjectTag\",\"value\":\"" + d + "\"}", o.toString());
assertEquals("\"" + d + "\"", o.toTagString());
//test equality
ObjectTag<DummyObject> o2 = new ObjectTag<>(d);
assertTrue(o.equals(o2));
ObjectTag<DummyObject> o3 = new ObjectTag<>(new DummyObject());
assertFalse(o.equals(o3));
ObjectTag<DummyObject> o4 = new ObjectTag<>(d.clone());
assertTrue(o.equals(o4));
//test cloning
ObjectTag<DummyObject> c = o.clone();
assertTrue(o.equals(c));
assertFalse(o == c);
assertFalse(o.getValue() == c.getValue());
ObjectTag<String> s = new ObjectTag<>("string");
ObjectTag<String> cs = s.clone();
assertTrue(s.equals(cs));
assertFalse(s == cs);
//String is immutable and not cloneable, so it still has the same reference
//noinspection StringEquality
assertTrue(s.getValue() == cs.getValue());
//test serialization
byte[] data = serialize(o);
ObjectTag<?> oo = ((ObjectTag<?>) deserialize(data));
assertNotNull(oo);
assertThrowsNoException(() -> oo.asTypedObjectTag(AbstractDummyObject.class));
assertThrowsException(() -> oo.asTypedObjectTag(String.class), ClassCastException.class);
ObjectTag<AbstractDummyObject> ooo = oo.asTypedObjectTag(AbstractDummyObject.class);
assertTrue(o.equals(ooo));
//test null value
ObjectTag<DummyObject> n = new ObjectTag<>();
assertNull(n.getValue());
assertEquals("{\"type\":\"ObjectTag\",\"value\":null}", n.toString());
assertEquals("null", n.toTagString());
ObjectTag<DummyObject> n2 = new ObjectTag<>(null);
assertTrue(n.equals(n2));
//null is equals to null, no matter the type
ObjectTag<String> n3 = new ObjectTag<>(null);
assertTrue(n.equals(n3));
ObjectTag<DummyObject> nc = n.clone();
assertTrue(n.equals(nc));
assertFalse(n == nc);
assertTrue(n.getValue() == nc.getValue());
data = serialize(n);
ObjectTag<?> nn = ((ObjectTag<?>) deserialize(data));
assertNotNull(nn);
ObjectTag<AbstractDummyObject> nnn = nn.asTypedObjectTag(AbstractDummyObject.class);
assertTrue(n.equals(nnn));
}
public void testCustomStructTag() {
StructTag.register();
StructTag s = new StructTag();
s.add(new ByteTag(Byte.MAX_VALUE));
s.add(new IntTag(Integer.MAX_VALUE));
assertEquals(120, s.getID());
assertEquals("[127b,2147483647]", s.toTagString());
assertEquals("{\"type\":\"StructTag\",\"value\":[{\"type\":\"ByteTag\",\"value\":127},{\"type\":\"IntTag\",\"value\":2147483647}]}", s.toString());
//test equality
StructTag s2 = new StructTag();
s2.add(new ByteTag(Byte.MAX_VALUE));
s2.add(new IntTag(Integer.MAX_VALUE));
assertTrue(s.equals(s2));
StructTag s3 = new StructTag();
s3.add(new IntTag(Integer.MAX_VALUE));
s3.add(new ByteTag(Byte.MAX_VALUE));
assertFalse(s.equals(s3));
StructTag s4 = new StructTag();
s4.add(new ByteTag(Byte.MAX_VALUE));
assertFalse(s.equals(s4));
//test cloning
StructTag c = s.clone();
assertTrue(s.equals(c));
assertFalse(s == c);
assertFalse(invokeGetValue(s) == invokeGetValue(c));
//test serialization
byte[] data = serialize(s);
assertTrue(Arrays.equals(new byte[]{120, 0, 0, 0, 0, 0, 2, 1, 127, 3, 127, -1, -1, -1}, data));
StructTag ss = (StructTag) deserialize(data);
assertTrue(s.equals(ss));
}
public void testWriteReadTag() {
CompoundTag t = new CompoundTag();
invokeSetValue(t, new LinkedHashMap<>());
t.putByte("byte", Byte.MAX_VALUE);
t.putShort("short", Short.MAX_VALUE);
File file = getNewTmpFile("compressed.dat");
try {
NBTUtil.writeTag(t, "name", file, true);
} catch (IOException ex) {
fail(ex.getMessage());
}
assertEquals("E8F7B55F81FADB8A5657461D9188DE73", calculateFileMD5(file));
try {
CompoundTag tt = (CompoundTag) NBTUtil.readTag(file);
assertTrue(t.equals(tt));
} catch (IOException ex) {
fail(ex.getMessage());
}
}
public void tearDown() throws Exception {
super.tearDown();
TagFactory.unregisterCustomTag(90);
TagFactory.unregisterCustomTag(100);
TagFactory.unregisterCustomTag(110);
TagFactory.unregisterCustomTag(120);
cleanupTmpDir();
}
private byte[] serialize(Tag tag) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
tag.serialize(dos, 0);
} catch (IOException ex) {
fail(ex.getMessage());
}
return baos.toByteArray();
}
private Tag deserialize(byte[] data) {
try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data))) {
return Tag.deserialize(dis, 0);
} catch (IOException ex) {
ex.printStackTrace();
fail(ex.getMessage());
return null;
}
}
private Tag deserializeFromFile(String f) {
URL resource = getClass().getClassLoader().getResource(f);
assertNotNull(resource);
File file = new File(resource.getFile());
try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) {
return Tag.deserialize(dis, 0);
} catch (IOException ex) {
ex.printStackTrace();
fail(ex.getMessage());
return null;
}
}
private <T> void invokeSetValue(Tag<T> tag, T value) {
try {
Class<?> c = tag.getClass();
Method m;
while (c != Object.class) {
try {
m = c.getDeclaredMethod("setValue", Object.class);
m.setAccessible(true);
m.invoke(tag, value);
return;
} catch (NoSuchMethodException ex) {
c = c.getSuperclass();
}
}
} catch (IllegalAccessException | InvocationTargetException e) {
fail("unable to invoke setValue() on " + tag.getClass().getSimpleName());
}
fail("could not find setValue()");
}
@SuppressWarnings("unchecked")
private <T> T invokeGetValue(Tag<T> tag) {
try {
Class<?> c = tag.getClass();
Method m;
while (c != Object.class) {
try {
m = c.getDeclaredMethod("getValue");
m.setAccessible(true);
return (T) m.invoke(tag);
} catch (NoSuchMethodException ex) {
c = c.getSuperclass();
}
}
} catch (IllegalAccessException | InvocationTargetException e) {
fail("unable to invoke getValue() on " + tag.getClass().getSimpleName());
}
fail("could not find getValue()");
return null;
}
}