Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NBTList.set throwing UnsupportedOperationException #10

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/me/nullicorn/nedit/type/NBTList.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public TagType getContentType() {
@Override
public Object set(int index, Object tag) {
checkType(tag);
return super.set(index, tag);
return decorated.set(index, tag);
}

/**
Expand Down
241 changes: 241 additions & 0 deletions src/test/java/me/nullicorn/nedit/type/NBTListTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
package me.nullicorn.nedit.type;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

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

@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
public class NBTListTests {

private Map<TagType, Object> testTags;
private Map<TagType, Object> alternativeTestTags;

@BeforeEach
void setUp() {
testTags = new HashMap<>();
testTags.put(TagType.BYTE, Byte.MAX_VALUE);
testTags.put(TagType.SHORT, Short.MAX_VALUE);
testTags.put(TagType.INT, Integer.MAX_VALUE);
testTags.put(TagType.LONG, Long.MAX_VALUE);
testTags.put(TagType.FLOAT, Float.MAX_VALUE);
testTags.put(TagType.DOUBLE, Double.MAX_VALUE);
testTags.put(TagType.BYTE_ARRAY, new byte[]{0, 1, 2, 3, 4});
testTags.put(TagType.STRING, "Hello, World!");
testTags.put(TagType.LIST, new NBTList(TagType.END));
testTags.put(TagType.COMPOUND, new NBTCompound());
testTags.put(TagType.INT_ARRAY, new int[]{0, 1, 2, 3, 4});
testTags.put(TagType.LONG_ARRAY, new long[]{0, 1, 2, 3, 4});

NBTCompound alternativeCompound = new NBTCompound();
alternativeCompound.put("alternative_value", 0);

alternativeTestTags = new HashMap<>();
alternativeTestTags.put(TagType.BYTE, Byte.MIN_VALUE);
alternativeTestTags.put(TagType.SHORT, Short.MIN_VALUE);
alternativeTestTags.put(TagType.INT, Integer.MIN_VALUE);
alternativeTestTags.put(TagType.LONG, Long.MIN_VALUE);
alternativeTestTags.put(TagType.FLOAT, Float.MIN_VALUE);
alternativeTestTags.put(TagType.DOUBLE, Double.MIN_VALUE);
alternativeTestTags.put(TagType.BYTE_ARRAY, new byte[]{4, 3, 2, 1, 0});
alternativeTestTags.put(TagType.STRING, "Goodbye, World!");
alternativeTestTags.put(TagType.LIST, new NBTList(TagType.BYTE));
alternativeTestTags.put(TagType.COMPOUND, alternativeCompound);
alternativeTestTags.put(TagType.INT_ARRAY, new int[]{4, 3, 2, 1, 0});
alternativeTestTags.put(TagType.LONG_ARRAY, new long[]{4, 3, 2, 1, 0});
}

@Test
void shouldHaveTheCorrectContentType() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);

assertEquals(type, list.getContentType());
});
}

@Test
void shouldAddValidTags() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);
assertEquals(0, list.size());

assertDoesNotThrow(() -> list.add(tag));

assertEquals(1, list.size());
assertFalse(list.isEmpty());
});
}

@Test
void shouldThrowWhenInvalidTagsAreAdded() {
NBTList list = new NBTList(TagType.BYTE);
Object invalidValue = new Object();
Class<? extends Throwable> expect = IllegalArgumentException.class;

assertThrows(expect, () -> list.add(invalidValue));
assertEquals(0, list.size());
assertTrue(list.isEmpty());
}

@Test
void shouldGetCorrectTags() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);
assertEquals(0, list.size());

assertDoesNotThrow(() -> list.add(tag));

assertEquals(1, list.size());
assertEquals(tag, list.get(0));
assertFalse(list.isEmpty());
});
}

@Test
void shouldGetCorrectTypes() {
checkGetter(list -> list::getByte, TagType.BYTE);
checkGetter(list -> list::getShort, TagType.SHORT);
checkGetter(list -> list::getInt, TagType.INT);
checkGetter(list -> list::getLong, TagType.LONG);
checkGetter(list -> list::getFloat, TagType.FLOAT);
checkGetter(list -> list::getDouble, TagType.DOUBLE);
checkGetter(list -> list::getByteArray, TagType.BYTE_ARRAY);
checkGetter(list -> list::getString, TagType.STRING);
checkGetter(list -> list::getList, TagType.LIST);
checkGetter(list -> list::getCompound, TagType.COMPOUND);
checkGetter(list -> list::getIntArray, TagType.INT_ARRAY);
checkGetter(list -> list::getLongArray, TagType.LONG_ARRAY);
}

@Test
void shouldThrowWhenInvalidGetterIsUsed() {
checkInvalidGetterThrows(list -> list::getByte, TagType.BYTE);
checkInvalidGetterThrows(list -> list::getShort, TagType.SHORT);
checkInvalidGetterThrows(list -> list::getInt, TagType.INT);
checkInvalidGetterThrows(list -> list::getLong, TagType.LONG);
checkInvalidGetterThrows(list -> list::getFloat, TagType.FLOAT);
checkInvalidGetterThrows(list -> list::getDouble, TagType.DOUBLE);
checkInvalidGetterThrows(list -> list::getByteArray, TagType.BYTE_ARRAY);
checkInvalidGetterThrows(list -> list::getString, TagType.STRING);
checkInvalidGetterThrows(list -> list::getList, TagType.LIST);
checkInvalidGetterThrows(list -> list::getCompound, TagType.COMPOUND);
checkInvalidGetterThrows(list -> list::getIntArray, TagType.INT_ARRAY);
checkInvalidGetterThrows(list -> list::getLongArray, TagType.LONG_ARRAY);
}

@Test
void shouldAddTagsInCorrectIndex() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);
assertEquals(0, list.size());

assertDoesNotThrow(() -> list.add(alternativeTestTags.get(type)));

assertDoesNotThrow(() -> list.add(0, tag));

assertEquals(list.get(0), tag);
assertEquals(list.get(1), alternativeTestTags.get(type));

assertEquals(2, list.size());
assertFalse(list.isEmpty());
});
}

@Test
void shouldAddAllValidTags() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);
assertEquals(0, list.size());

assertDoesNotThrow(() -> list.addAll(Arrays.asList(tag, alternativeTestTags.get(type))));

assertEquals(2, list.size());
assertEquals(tag, list.get(0));
assertEquals(alternativeTestTags.get(type), list.get(1));
assertFalse(list.isEmpty());
});
}

@Test
void shouldThrowWhenInvalidTagsAreAddAlled() {
NBTList list = new NBTList(TagType.BYTE);
Object invalidValue = new Object();
Class<? extends Throwable> expect = IllegalArgumentException.class;

assertThrows(expect, () -> list.addAll(Collections.singletonList(invalidValue)));
assertThrows(expect, () -> list.addAll(Arrays.asList(testTags.get(TagType.BYTE), invalidValue)));
assertThrows(expect, () -> list.addAll(Arrays.asList(invalidValue, testTags.get(TagType.BYTE))));
assertEquals(0, list.size());
assertTrue(list.isEmpty());
}

@Test
void shouldSetValidTags() {
testTags.forEach((type, tag) -> {
NBTList list = new NBTList(type);
assertEquals(0, list.size());

assertDoesNotThrow(() -> list.add(alternativeTestTags.get(type)));

assertDoesNotThrow(() -> list.set(0, tag));

assertEquals(1, list.size());
assertEquals(tag, list.get(0));
assertFalse(list.isEmpty());
});
}

@Test
void shouldThrowWhenInvalidTagsAreSet() {
NBTList list = new NBTList(TagType.BYTE);
Object invalidValue = new Object();
Class<? extends Throwable> expect = IllegalArgumentException.class;
assertDoesNotThrow(() -> list.add(testTags.get(TagType.BYTE)));

assertThrows(expect, () -> list.set(0, invalidValue));
assertEquals(testTags.get(TagType.BYTE), list.get(0));
}

/**
* Assert that a list's {@code getter} for a tag type returns the same value
* that was inputted. The expected value comes from the {@link #testTags}
* map.
*/
private <T> void checkGetter(Function<NBTList, Function<Integer, T>> getter, TagType type) {
Object tag = testTags.get(type);
NBTList list = new NBTList(type);

assertDoesNotThrow(() -> list.add(tag));

T returned = getter.apply(list).apply(0);

assertEquals(tag, returned);
assertEquals(tag.getClass(), returned.getClass());
}

/**
* Assert that a list's {@code getter} for a tag type throws an exception
* when it is used for a list of a different tag type
*/
private <T> void checkInvalidGetterThrows(Function<NBTList, Function<Integer, T>> getter, TagType type) {
testTags.forEach((differentType, tag) -> {
// Only run on different types
if (differentType != type) {
NBTList list = new NBTList(differentType);
Class<? extends Throwable> expect = IllegalStateException.class;

assertDoesNotThrow(() -> list.add(tag));

assertThrows(expect, () -> getter.apply(list).apply(0));
}
});
}

}