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

Add unit tests for dough-data #65

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
24e1a1b
Add unit tests for CopyUtils
md5sha256 Jul 29, 2021
025f787
Merge branch 'main' into tests/copy-utils
md5sha256 Jul 29, 2021
dc88fb3
Make DummyData package-private
md5sha256 Jul 29, 2021
97136c2
Add unit tests for the dough-data blocks api
md5sha256 Aug 5, 2021
97ec643
Add unit tests for CopyUtils
md5sha256 Jul 29, 2021
a29531d
Make DummyData package-private
md5sha256 Jul 29, 2021
2cad21d
Add unit tests for the dough-data blocks api
md5sha256 Aug 5, 2021
0cce86f
Merge branch 'tests/dough-data' of https://github.com/baked-libs/doug…
md5sha256 Aug 5, 2021
7b16a0b
Address PR changes
md5sha256 Aug 6, 2021
257e968
Add tests for WeightedNode
md5sha256 Aug 6, 2021
e951ac6
Add CollectionTestUtils and TestLoopIterator
md5sha256 Aug 6, 2021
de407ed
Add test for empty iterator in TestLoopIterator
md5sha256 Aug 6, 2021
3079c80
Add tests for Pair and OptionalPair
md5sha256 Aug 6, 2021
b2db9d3
Add tests for OptionalMap
md5sha256 Aug 7, 2021
11c20de
Add tests for KeyMap
md5sha256 Aug 7, 2021
3b00a9b
Add tests for TriStateOptional
md5sha256 Aug 7, 2021
6651fb8
Add tests for RandomizedSet
md5sha256 Aug 8, 2021
014f71b
Fix code smells
md5sha256 Aug 8, 2021
fa27c37
Merge branch 'main' into tests/dough-data
md5sha256 Aug 8, 2021
13b419c
Fix package
md5sha256 Aug 8, 2021
aba3d52
Initial work on TestPersistentUUID and fixes for PerisstentUUID
md5sha256 Aug 8, 2021
57daeca
Add tests for PersistentYAMLDataType
md5sha256 Aug 8, 2021
a6c3243
Fix access modifier
md5sha256 Aug 8, 2021
8710733
Add tests for PersistJsonDataTypea
md5sha256 Aug 8, 2021
58da2fd
Merge branch 'main' into tests/dough-data
TheBusyBiscuit Jan 7, 2022
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
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ public Optional<T> find(@Nonnull Predicate<T> predicate) {
int start = index;

T current = next();
while (index != start || predicate.test(current)) {
while (index != start && !predicate.test(current)) {
current = next();
}

Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ private PersistentUUIDDataType() {}
Validate.notNull(ints, "The provided integer array cannot be null!");
Validate.isTrue(ints.length == 4, "The integer array must have a length of 4.");

return new UUID(ints[0] | ints[1] & 0xFFFFFFFFL, ints[2] | ints[3] & 0xFFFFFFFFL);
return new UUID(((long) ints[0] << 32) | ints[1] & 0xFFFFFFFFL, ((long) ints[2] << 32) | ints[3] & 0xFFFFFFFFL);
}

public static @Nonnull int[] toIntArray(@Nonnull UUID uuid) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.github.bakedlibs.dough.blocks;

import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.WorldMock;
import org.bukkit.Location;
import org.bukkit.World;
import org.junit.jupiter.api.*;

class TestBlockPosition {

@BeforeAll
static void init() {
MockBukkit.mock();
}

@AfterAll
static void teardown() {
MockBukkit.unmock();
}

@Test
@DisplayName("Test the coordinate getters")
void testCoordinateGetters() {
int x = 10;
int y = 1000;
int z = 50;
World world = new WorldMock();
BlockPosition blockPosition = new BlockPosition(world, x, y, z);
Assertions.assertEquals(x, blockPosition.getX());
Assertions.assertEquals(y, blockPosition.getY());
Assertions.assertEquals(z, blockPosition.getZ());
}

@Test
void testCloning() {
int x = 10;
int y = 1000;
int z = 50;
World world = new WorldMock();
BlockPosition blockPosition = new BlockPosition(world, x, y, z);
Location location = blockPosition.toLocation();
Assertions.assertEquals(blockPosition.getPosition(), BlockPosition.getAsLong(location));
Assertions.assertEquals(blockPosition, new BlockPosition(world, blockPosition.getPosition()));
Assertions.assertEquals(x, location.getBlockX());
Assertions.assertEquals(y, location.getBlockY());
Assertions.assertEquals(z, location.getBlockZ());
Assertions.assertEquals(blockPosition, new BlockPosition(location));
Assertions.assertEquals(blockPosition.hashCode(), new BlockPosition(location).hashCode());
Assertions.assertEquals(x >> 4, blockPosition.getChunkX());
Assertions.assertEquals(z >> 4, blockPosition.getChunkZ());
}

@Test
void testInvalidWorld() {
World world = new WorldMock();
BlockPosition position = new BlockPosition(world, 1, 1, 1);
BlockPosition copy = new BlockPosition(world, 1, 1, 1);
world = null;
// Force garbage collection
System.gc();
String msg = "The reference of this BlockPositions world has been cleared";
Assertions.assertThrows(IllegalStateException.class, position::getWorld, msg);
Assertions.assertThrows(IllegalStateException.class, position::getBlock, msg);
Assertions.assertThrows(IllegalStateException.class, position::getChunk, msg);
// If the world is un-loaded the equals method should always return false.
Assertions.assertNotEquals(position, copy);
}

@Test
void testInvalidEquality() {
World world = new WorldMock();
Assertions.assertNotEquals(1, new BlockPosition(world, 1, 1, 1));
}

@Test
void testToString() {
String name = "world";
WorldMock world = new WorldMock();
world.setName(name);
BlockPosition position = new BlockPosition(world, 1, 1, 1);
String expected = "BlockPosition(world=world, x=1, y=1, z=1, position=" + position.getPosition() + ")";
Assertions.assertEquals(expected, position.toString());
String expectedNoRef = "BlockPosition(world=<no reference>, x=1, y=1, z=1, position=" + position.getPosition() + ")";
world = null;
// Force GC
System.gc();
Assertions.assertEquals(expectedNoRef, position.toString());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package io.github.bakedlibs.dough.blocks;

import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.WorldMock;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.junit.jupiter.api.*;

class TestChunkPosition {

@BeforeAll
static void init() {
MockBukkit.mock();
}

@AfterAll
static void teardown() {
MockBukkit.unmock();
}

@Test
@DisplayName("Test the coordinate getters")
void testCoordinateGetters() {
int x = 10;
int z = 50;
World world = new WorldMock();
ChunkPosition chunkPosition = new ChunkPosition(world, x, z);
Assertions.assertEquals(x, chunkPosition.getX());
Assertions.assertEquals(z, chunkPosition.getZ());
}

@Test
void testConstructors() {
int x = 10;
int z = 50;
World world = new WorldMock();
ChunkPosition chunkPosition = new ChunkPosition(world, x, z);
ChunkPosition fromLocation = new ChunkPosition(new Location(world, x << 4, 1, z << 4));
Assertions.assertEquals(chunkPosition, fromLocation);
Assertions.assertEquals(chunkPosition.hashCode(), fromLocation.hashCode());
Assertions.assertEquals(chunkPosition, new ChunkPosition(world.getChunkAt(x, z)));
Assertions.assertEquals(chunkPosition.getPosition(), ChunkPosition.getAsLong(x, z));
Assertions.assertEquals(chunkPosition, new ChunkPosition(world, chunkPosition.getPosition()));
}

@Test
void testInvalidWorld() {
World world = new WorldMock();
ChunkPosition position = new ChunkPosition(world, 1, 1);
ChunkPosition copy = new ChunkPosition(world, 1, 1);
world = null;
// Force garbage collection
System.gc();
String msg = "The reference of this ChunkPositions world has been cleared";
Assertions.assertThrows(IllegalStateException.class, position::getWorld, msg);
Assertions.assertThrows(IllegalStateException.class, position::getChunk, msg);
// If the world is un-loaded the equals method should always return false.
Assertions.assertNotEquals(position, copy);
}

@Test
void testInvalidEquality() {
World world = new WorldMock();
Assertions.assertNotEquals(1, new ChunkPosition(world, 1, 1));
}

@Test
void testToString() {
String name = "world";
WorldMock world = new WorldMock();
world.setName(name);
ChunkPosition position = new ChunkPosition(world, 1, 1);
String expected = "ChunkPosition(world=world, x=1, z=1, position=" + position.getPosition() + ")";
Assertions.assertEquals(expected, position.toString());
String expectedNoRef = "ChunkPosition(world=<no reference>, x=1, z=1, position=" + position.getPosition() + ")";
world = null;
// Force GC
System.gc();
Assertions.assertEquals(expectedNoRef, position.toString());
}

@Test
void testIsLoaded() {
World world = new WorldMock();
Chunk chunk = world.getChunkAt(1, 1);
ChunkPosition position = new ChunkPosition(chunk);
Assertions.assertEquals(chunk.isLoaded(), position.isLoaded());
chunk = null;
world = null;
// Force GC
System.gc();
Assertions.assertFalse(position.isLoaded());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.github.bakedlibs.dough.collections;

import org.junit.jupiter.api.Assertions;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Map;

public class CollectionTestUtils {

static <T> void assertHaveEqualElements(@Nonnull Collection<T> c1, @Nonnull Collection<T> c2) {
Assertions.assertEquals(c1.size(), c2.size());
Assertions.assertTrue(c1.containsAll(c2));
}

static <K, V> void assertHaveEqualElements(@Nonnull Map<K, V> m1, @Nonnull Map<K, V> m2) {
Assertions.assertEquals(m1.size(), m2.size());
for (Map.Entry<K, V> entry : m1.entrySet()) {
Assertions.assertEquals(m2.get(entry.getKey()), entry.getValue());
}
}

static <T> void assertHaveClonedElements(@Nonnull Collection<T> c1, @Nonnull Collection<T> c2) {
Assertions.assertEquals(c1.size(), c2.size());
for (T t1 : c1) {
for (T t2 : c2) {
// If they are the same, it did not clone and thus we fail.
Assertions.assertNotSame(t1, t2);
if (t1.equals(t2)) {
// If they are equal, the element has been cloned, thus, we break and check the next element.
break;
}
}
}
}

static <K, V> void assertHaveClonedElements(@Nonnull Map<K, V> m1, @Nonnull Map<K, V> m2) {
Assertions.assertEquals(m1.size(), m2.size());
for (Map.Entry<K, V> entry : m1.entrySet()) {
V otherValue = m2.get(entry.getKey());
// If they are the same, it did not clone and thus we fail.
Assertions.assertNotSame(entry.getValue(), otherValue);
if (entry.getValue().equals(otherValue)) {
// If they are equal, the element has been cloned, thus, we break and check the next element.
break;
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.github.bakedlibs.dough.collections;

import javax.annotation.Nonnull;

class DummyData implements Cloneable {

private final int value;

DummyData(int value) {
this.value = value;
}

private DummyData(@Nonnull DummyData other) {
this.value = other.value;
}

@Override
public @Nonnull DummyData clone() {
try {
super.clone();
} catch (CloneNotSupportedException ex) {
ex.printStackTrace();
}
return new DummyData(this);
}

@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;

DummyData dummyData = (DummyData) o;

return value == dummyData.value;
}

@Override
public int hashCode() {
return value;
}

@Override
public String toString() {
return "DummyData{" + "value=" + value + '}';
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.bakedlibs.dough.collections;

import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;

import javax.annotation.Nonnull;

public class DummyKeyed implements Keyed {

private final NamespacedKey key;

public DummyKeyed(@Nonnull NamespacedKey key) {
this.key = key;
}

@Override
public @Nonnull NamespacedKey getKey() {
return key;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.github.bakedlibs.dough.collections;

import org.junit.jupiter.api.Assertions;

public class PairUtils {

static <P, S> void assertValues(Pair<P, S> pair, P expectedPrimary, S expectedSecondary) {
Assertions.assertSame(expectedPrimary, pair.getFirstValue());
Assertions.assertSame(expectedSecondary, pair.getSecondValue());
}

static <P, S> void assertValues(OptionalPair<P, S> pair, P expectedPrimary, S expectedSecondary) {
if (expectedPrimary == null) {
Assertions.assertFalse(pair.getFirstValue().isPresent());
} else {
Assertions.assertEquals(expectedPrimary, pair.getFirstValue().orElse(null));
}
if (expectedSecondary == null) {
Assertions.assertFalse(pair.getSecondValue().isPresent());
} else {
Assertions.assertEquals(expectedSecondary, pair.getSecondValue().orElse(null));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.github.bakedlibs.dough.collections;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

class TestCopyUtils {

@Test
@DisplayName("Test if collections are deeply cloned properly")
void testCloningCollections() {
Collection<DummyData> dummyCollection =
Arrays.asList(new DummyData(1), new DummyData(2), new DummyData(3));
Collection<DummyData> clonedCollection =
CopyUtils.deepCopy(dummyCollection, DummyData::clone, ArrayList::new);
CollectionTestUtils.assertHaveEqualElements(dummyCollection, clonedCollection);
CollectionTestUtils.assertHaveClonedElements(dummyCollection, clonedCollection);
}

@Test
@DisplayName("Test if maps are deeply cloned properly")
void testCloningMaps() {
Map<Integer, DummyData> dummyMap = new HashMap<>();
dummyMap.put(1, new DummyData(1));
dummyMap.put(2, new DummyData(2));
dummyMap.put(3, new DummyData(3));
Map<Integer, DummyData> clonedMap = CopyUtils.deepCopy(dummyMap, DummyData::clone, HashMap::new);
CollectionTestUtils.assertHaveEqualElements(dummyMap, clonedMap);
CollectionTestUtils.assertHaveClonedElements(dummyMap, clonedMap);
// We first perform a shallow copy from clonedMap
Map<Integer, DummyData> clonedMapDeepCopy = new HashMap<>(clonedMap);
// We then mutate the shallow copy and turn it into a deep copy.
CopyUtils.deepCopy(clonedMapDeepCopy, DummyData::clone);
CollectionTestUtils.assertHaveEqualElements(clonedMap, clonedMapDeepCopy);
CollectionTestUtils.assertHaveClonedElements(clonedMap, clonedMapDeepCopy);
}

@Test
@DisplayName("Test if arrays are deeply cloned properly")
void testCloningArrays() {
DummyData[] dummyArray = new DummyData[]{new DummyData(1), new DummyData(2), new DummyData(3)};
DummyData[] clonedArray = CopyUtils.deepCopy(dummyArray, DummyData::clone, DummyData[]::new);
CollectionTestUtils.assertHaveEqualElements(Arrays.asList(dummyArray), Arrays.asList(clonedArray));
CollectionTestUtils.assertHaveClonedElements(Arrays.asList(dummyArray), Arrays.asList(clonedArray));
DummyData[] deepClonedArray = new DummyData[clonedArray.length];
CopyUtils.deepCopy(clonedArray, DummyData::clone, deepClonedArray);
CollectionTestUtils.assertHaveEqualElements(Arrays.asList(dummyArray), Arrays.asList(deepClonedArray));
CollectionTestUtils.assertHaveClonedElements(Arrays.asList(dummyArray), Arrays.asList(deepClonedArray));
// Cannot clone if the length of the sink < length of source
DummyData[] invalidArray = new DummyData[clonedArray.length - 1];
Assertions.assertThrows(IllegalArgumentException.class, () -> CopyUtils.deepCopy(dummyArray, DummyData::clone, invalidArray));
try {
DummyData[] validArray = new DummyData[clonedArray.length + 1];
CopyUtils.deepCopy(dummyArray, DummyData::clone, validArray);
} catch (Exception ex) {
// Unexpected failure
Assertions.fail(ex);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.bakedlibs.dough.collections;

import org.bukkit.NamespacedKey;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

class TestKeyMap {

@Test
@DisplayName("Test if the add method uses the correct key")
@SuppressWarnings("deprecation")
void testAdd() {
NamespacedKey key = new NamespacedKey("abc", "def");
DummyKeyed dummyKeyed = new DummyKeyed(key);
KeyMap<DummyKeyed> keyMap1 = new KeyMap<>();
keyMap1.add(dummyKeyed);
Assertions.assertEquals(dummyKeyed, keyMap1.get(dummyKeyed.getKey()).orElse(null));
}

@Test
@DisplayName("Test if the constructor uses the output of the supplier")
void testConstructor() {
Map<NamespacedKey, DummyKeyed> map = new HashMap<>();
KeyMap<DummyKeyed> keyMap2 = new KeyMap<>(() -> map);
Assertions.assertSame(map, keyMap2.getInternalMap());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.bakedlibs.dough.collections;

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

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

class TestLoopIterator {

@Test
void testLooping() {
Collection<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
LoopIterator<Integer> iterator = new LoopIterator<>(integers);
Assertions.assertTrue(iterator.hasNext());
int index = 0;
for (Integer integer : integers) {
Assertions.assertTrue(iterator.hasNext());
Assertions.assertEquals(index, iterator.getIndex());
Assertions.assertEquals(integer, iterator.next());
index++;
}
// Check loop
Assertions.assertTrue(iterator.hasNext());
Assertions.assertEquals(1, iterator.next());
}

@Test
void testStream() {
Collection<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
LoopIterator<Integer> iterator = new LoopIterator<>(integers);
Collection<Integer> integersCopy = iterator
.stream()
.limit(integers.size())
.collect(Collectors.toList());
CollectionTestUtils.assertHaveEqualElements(integers, integersCopy);
}

@Test
void testInvalidCases() {
LoopIterator<Object> emptyIterator = new LoopIterator<>(Collections.emptyList());
Assertions.assertFalse(emptyIterator.hasNext());
Assertions.assertThrows(NoSuchElementException.class, emptyIterator::next, "The given collection was empty.");
Assertions.assertThrows(IllegalArgumentException.class, () -> new LoopIterator<>(emptyIterator), "Cannot loop-iterate over a LoopIterator");
}

@Test
void testFinding() {
Collection<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
LoopIterator<Integer> iterator = new LoopIterator<>(integers);
Assertions.assertTrue(iterator.find(i -> i <= 10 && i > 0).isPresent());
Assertions.assertFalse(iterator.find(i -> i > 10 || i < 1).isPresent());
}

@Test
void testEmptyIterator() {
LoopIterator<Object> emptyIterator = new LoopIterator<>(Collections.emptyList());
Assertions.assertFalse(emptyIterator.find(x -> true).isPresent());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package io.github.bakedlibs.dough.collections;

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

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

class TestOptionalMap {

@Test
void testNullSupplier() {
Assertions.assertThrows(IllegalStateException.class, () -> new OptionalMap<>(() -> null), "Internal Map is not allowed to be null!");
}

@Test
void testGetters() {
Map<Integer, Integer> map = Collections.emptyMap();
OptionalMap<Integer, Integer> optionalMap = new OptionalMap<>(() -> map);
Assertions.assertFalse(optionalMap.get(1).isPresent());
Assertions.assertFalse(optionalMap.containsKey(1));
Assertions.assertFalse(optionalMap.containsValue(1));
Assertions.assertEquals(0, optionalMap.size());
Assertions.assertSame(map.keySet(), optionalMap.keySet());
Assertions.assertSame(map.entrySet(), optionalMap.entrySet());
Assertions.assertSame(map.values(), optionalMap.values());
Assertions.assertSame(map.entrySet().iterator(), optionalMap.iterator());
Assertions.assertSame(map, optionalMap.getInternalMap());
Assertions.assertEquals(optionalMap, map);
Assertions.assertEquals(map.hashCode(), optionalMap.hashCode());
Assertions.assertEquals(1, optionalMap.getOrDefault(10, 1));
}

@Test
void testMapModification() {
OptionalMap<Integer, Integer> map = new OptionalMap<>(HashMap::new);
map.put(1, 1);
Assertions.assertTrue(map.containsKey(1));
Assertions.assertTrue(map.get(1).isPresent());
Assertions.assertEquals(1, map.get(1).orElse(null));
Assertions.assertEquals(1, map.size());
map.clear();
Assertions.assertEquals(0, map.size());
Assertions.assertTrue(map.isEmpty());
map.put(1, 1);
Assertions.assertThrows(RuntimeException.class,
() -> map.ifPresent(1, x -> {
throw new RuntimeException("Value = " + x);
}), "Value = 1");
map.remove(1);
Assertions.assertThrows(RuntimeException.class,
() -> map.ifAbsent(1, v -> {
// The value passed here must always be null
Assertions.assertNull(v);
throw new RuntimeException("Value not found!");
}), "Value not found!");
Assertions.assertEquals(2, map.computeIfAbsent(2, k -> k));
Assertions.assertEquals(3, map.computeIfPresent(2, (k, v) -> v + 1));
Assertions.assertNull(map.compute(4, (k, v) -> null));
Assertions.assertEquals(4, map.compute(4, (k, v) -> k));
// The value in the map for key=4 is 4, here we merge the values by summing them together.
Assertions.assertEquals(8, map.merge(4, 4, Integer::sum));
// Since the value mapped for key=4 is 8, we check to see if 8 is whats returned.
Assertions.assertEquals(8, map.putIfAbsent(4, 4));
// No value for key=5 so it should be null
Assertions.assertNull(map.putIfAbsent(5, 5));
Assertions.assertEquals(5, map.get(5).orElse(null));
Map<Integer, Integer> map2 = new HashMap<>();
map2.put(6, 6);
map2.put(7, 7);
map.putAll(map2);
Assertions.assertEquals(6, map.get(6).orElse(null));
Assertions.assertEquals(7, map.get(7).orElse(null));
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.github.bakedlibs.dough.collections;

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

import java.util.AbstractMap;
import java.util.Map;

class TestOptionalPair {

@Test
void testGettersAndSetters() {

Object primary = new Object();

Map.Entry<Object, Object> entry = new AbstractMap.SimpleEntry<>(primary, null);
OptionalPair<Object, Object> pair = new OptionalPair<>(primary, null);
OptionalPair<Object, Object> pairFromEntry = new OptionalPair<>(entry);

PairUtils.assertValues(pair, primary, null);
PairUtils.assertValues(pairFromEntry, primary, null);

Object modifiedSecondary = new Object();

pair.setFirstValue(null);
pair.setSecondValue(modifiedSecondary);
PairUtils.assertValues(pair, null, modifiedSecondary);

}

@Test
void testEquality() {

Object primary = new Object();
Object secondary = new Object();

Map.Entry<Object, Object> entry = new AbstractMap.SimpleEntry<>(primary, secondary);
OptionalPair<Object, Object> optionalPair = new OptionalPair<>(primary, secondary);
OptionalPair<Object, Object> pairFromEntry = new OptionalPair<>(entry);
OptionalPair<Object, Object> optionalPairFromPair = new OptionalPair<>(new Pair<>(primary, secondary));

Assertions.assertTrue(optionalPairFromPair.getFirstValue().isPresent());
Assertions.assertTrue(optionalPairFromPair.getSecondValue().isPresent());

Assertions.assertEquals(optionalPair, optionalPairFromPair);
Assertions.assertEquals(optionalPair.hashCode(), optionalPairFromPair.hashCode());
Assertions.assertEquals(optionalPair, pairFromEntry);
Assertions.assertEquals(optionalPair.hashCode(), optionalPairFromPair.hashCode());
Assertions.assertEquals(optionalPair, optionalPair);

Assertions.assertNotEquals(null, optionalPair);
Assertions.assertEquals(optionalPair, new OptionalPair<>(primary, secondary));
Assertions.assertNotEquals(optionalPair, new OptionalPair<>(primary, null));
Assertions.assertNotEquals(optionalPair, new OptionalPair<>(null, secondary));

OptionalPair<Object, Integer> differentTypePair = new OptionalPair<>(primary, 10);
Assertions.assertNotEquals(optionalPair, differentTypePair);

}

@Test
void testToString() {
OptionalPair<Integer, Integer> pair = new OptionalPair<>(1, null);
String expected = "OptionalPair(firstValue=Optional[1], secondValue=Optional.empty)";
Assertions.assertEquals(expected, pair.toString());
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.github.bakedlibs.dough.collections;

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

import java.util.AbstractMap;
import java.util.Map;

class TestPair {

@Test
void testGettersAndSetters() {

Object primary = new Object();
Object secondary = new Object();

Map.Entry<Object, Object> entry = new AbstractMap.SimpleEntry<>(primary, secondary);
OptionalPair<Object, Object> optionalPair = new OptionalPair<>(primary, secondary);
Pair<Object, Object> pair = new Pair<>(primary, secondary);
Pair<Object, Object> pairFromOptional = new Pair<>(optionalPair);
Pair<Object, Object> pairFromEntry = new Pair<>(entry);

PairUtils.assertValues(pair, primary, secondary);
PairUtils.assertValues(pairFromOptional, primary, secondary);
PairUtils.assertValues(pairFromEntry, primary, secondary);

Object modifiedPrimary = new Object();
Object modifiedSecondary = new Object();

pair.setFirstValue(modifiedPrimary);
pair.setSecondValue(modifiedSecondary);
PairUtils.assertValues(pair, modifiedPrimary, modifiedSecondary);

}

@Test
void testEquality() {
Object primary = new Object();
Object secondary = new Object();

Map.Entry<Object, Object> entry = new AbstractMap.SimpleEntry<>(primary, secondary);
OptionalPair<Object, Object> optionalPair = new OptionalPair<>(primary, secondary);
Pair<Object, Object> pair = new Pair<>(primary, secondary);
Pair<Object, Object> pairFromOptional = new Pair<>(optionalPair);
Pair<Object, Object> pairFromEntry = new Pair<>(entry);

Assertions.assertEquals(pair, pairFromOptional);
Assertions.assertEquals(pair.hashCode(), pairFromOptional.hashCode());
Assertions.assertEquals(pair, pairFromEntry);
Assertions.assertEquals(pair.hashCode(), pairFromOptional.hashCode());
Assertions.assertEquals(pair, pair);

Assertions.assertNotEquals(null, pair);
Assertions.assertEquals(pair, new Pair<>(primary, secondary));
Assertions.assertNotEquals(pair, new Pair<>(primary, new Object()));
Assertions.assertNotEquals(pair, new Pair<>(new Object(), secondary));

Pair<Object, Integer> differentTypePair = new Pair<>(primary, 10);
Assertions.assertNotEquals(pair, differentTypePair);

}

@Test
void testToString() {
Pair<Integer, Integer> pair = new Pair<>(1, 2);
String expected = "Pair(firstValue=1, secondValue=2)";
Assertions.assertEquals(expected, pair.toString());
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.github.bakedlibs.dough.collections;

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

import java.util.*;

class TestRandomizedSet {

@Test
void testModification() {
RandomizedSet<Integer> randomizedSet = new RandomizedSet<>();
Assertions.assertTrue(randomizedSet.isEmpty());
Assertions.assertEquals(0, randomizedSet.size());
Assertions.assertThrows(IllegalArgumentException.class, () -> randomizedSet.add(1, 0), "A Weight may never be less than or equal to zero!");
Assertions.assertTrue(randomizedSet.add(1, 1));
Assertions.assertEquals(1, randomizedSet.size());
Assertions.assertEquals(1, randomizedSet.sumWeights());
Assertions.assertThrows(IllegalArgumentException.class, () -> randomizedSet.setWeight(1, 0), "A Weight may never be less than or equal to zero!");
randomizedSet.setWeight(1, 0.5f);
Assertions.assertEquals(0.5f, randomizedSet.sumWeights());
randomizedSet.setWeight(1, 1);
Assertions.assertThrows(IllegalStateException.class, () -> randomizedSet.setWeight(2, 1), "The specified Object is not contained in this Set");
Assertions.assertFalse(randomizedSet.add(1, 2));
// There is only one element in the set.
Assertions.assertEquals(1, randomizedSet.getRandom());
Assertions.assertTrue(randomizedSet.remove(1));
Assertions.assertNull(randomizedSet.getRandom());
Assertions.assertFalse(randomizedSet.remove(1));
randomizedSet.add(1, 1f);
randomizedSet.clear();
Assertions.assertTrue(randomizedSet.isEmpty());
Assertions.assertEquals(0, randomizedSet.sumWeights());

}

@Test
void testProbability() {
RandomizedSet<Integer> randomizedSet = new RandomizedSet<>();
randomizedSet.add(1, 1);
randomizedSet.add(2, 1);
Assertions.assertEquals(2, randomizedSet.sumWeights());
Map<Integer, Float> expectedWeights = new HashMap<>();
expectedWeights.put(1, 0.5f);
expectedWeights.put(2, 0.5f);
CollectionTestUtils.assertHaveEqualElements(expectedWeights, randomizedSet.toMap());
int ones = 0;
int twos = 0;
for (int i = 0; i < 1000; i++) {
if (randomizedSet.getRandom() == 1) {
ones++;
} else {
twos++;
}
}
// +- 10%
Assertions.assertEquals(500, ones, 50);
Assertions.assertEquals(500, twos, 50);
}

@Test
void testRandomSubset() {
// 1, 2, 3, and 4 have an equal weight.
RandomizedSet<Integer> randomizedSet = new RandomizedSet<>(Arrays.asList(1, 2, 3, 4));
Set<Integer> set = randomizedSet.getRandomSubset(2);
Assertions.assertEquals(2, set.size());
Assertions.assertTrue(Arrays.asList(1, 2, 3, 4).containsAll(set));
Assertions.assertThrows(IllegalArgumentException.class, () -> randomizedSet.getRandomSubset(5), "A random Subset may not be larger than the original Set! (5 > 4");
Set<Integer> sameSizeSet = randomizedSet.getRandomSubset(4);
Assertions.assertEquals(4, sameSizeSet.size());
CollectionTestUtils.assertHaveEqualElements(new HashSet<>(Arrays.asList(1, 2, 3, 4)), sameSizeSet);
CollectionTestUtils.assertHaveEqualElements(sameSizeSet, Arrays.asList(randomizedSet.toArray(Integer[]::new)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.github.bakedlibs.dough.collections;

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

class TestWeightedNode {

@Test
void testGettersAndSetters() {
float weight1 = 1.0f;
float weight2 = 2.0f;
Object object1 = new Object();
Object object2 = new Object();
WeightedNode<Object> node = new WeightedNode<>(weight1, object1);
Assertions.assertSame(object1, node.getObject());
Assertions.assertEquals(weight1, node.getWeight());
node.setWeight(weight2);
node.setObject(object2);
Assertions.assertSame(object2, node.getObject());
Assertions.assertEquals(weight2, node.getWeight());
Assertions.assertThrows(IllegalArgumentException.class, () -> node.setObject(null), "Object cannot be null");
}

@Test
void testEqualityChecking() {
float weight = 1.0f;
Object object = new Object();
WeightedNode<Object> node = new WeightedNode<>(weight, object);
WeightedNode<Object> similarNode = new WeightedNode<>(weight, object);
Assertions.assertNotSame(node, similarNode);
Assertions.assertEquals(node, similarNode);
Assertions.assertEquals(node.hashCode(), similarNode.hashCode());
WeightedNode<Object> differentNode = new WeightedNode<>(weight, weight);
Assertions.assertNotEquals(node, differentNode);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package io.github.bakedlibs.dough.data;

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

class TestTriStateOptional {

@Test
void testEmpty() {
TriStateOptional<Object> empty = TriStateOptional.empty();
TriStateOptional<Object> nullObject = TriStateOptional.ofNullable(null);
Assertions.assertTrue(nullObject.isEmpty());

Assertions.assertTrue(empty.isEmpty());
Assertions.assertTrue(empty.isComputed());
Assertions.assertFalse(empty.isPresent());
Assertions.assertThrows(IllegalAccessError.class, empty::get, "This Optional has no value! Check .isPresent() first!");
Assertions.assertNull(empty.getOrElse(null));
Assertions.assertFalse(empty.getAsOptional().isPresent());
}

@Test
void testComputed() {
TriStateOptional<Object> computed = TriStateOptional.createNew();
Assertions.assertFalse(computed.isEmpty());
Assertions.assertFalse(computed.isComputed());
Assertions.assertFalse(computed.isPresent());
Assertions.assertThrows(IllegalAccessError.class, computed::get, "This Optional has no value! Check .isPresent() first!");
Assertions.assertThrows(IllegalStateException.class, () -> computed.getOrElse(null), "This Optional has not yet been computed!");
Assertions.assertThrows(IllegalStateException.class, computed::getAsOptional, "This Optional has not yet been computed!");
}

@Test
void testPresent() {
Object object = new Object();
TriStateOptional<Object> present = TriStateOptional.of(object);
Assertions.assertFalse(present.isEmpty());
Assertions.assertTrue(present.isComputed());
Assertions.assertSame(object, present.get());
Assertions.assertSame(object, present.getOrElse(null));
Assertions.assertTrue(present.getAsOptional().isPresent());
Assertions.assertSame(object, present.getAsOptional().orElse(null));
TriStateOptional<Object> presentFromNullable = TriStateOptional.ofNullable(object);
Assertions.assertFalse(presentFromNullable.isEmpty());
Assertions.assertTrue(presentFromNullable.isComputed());
Assertions.assertSame(object, presentFromNullable.get());
Assertions.assertSame(object, presentFromNullable.getOrElse(null));
Assertions.assertTrue(presentFromNullable.getAsOptional().isPresent());
Assertions.assertSame(object, presentFromNullable.getAsOptional().orElse(null));
}

@Test
void testCompute() {
Object computedValue = new Object();
TriStateOptional<Object> computed = TriStateOptional.createNew();
Assertions.assertFalse(computed.isComputed());
computed.compute(computedValue);
Assertions.assertTrue(computed.isComputed());
Assertions.assertEquals(computedValue, computed.get());
Assertions.assertEquals(computedValue, computed.getOrElse(null));
Assertions.assertEquals(computedValue, computed.getAsOptional().orElse(null));
Assertions.assertThrows(IllegalStateException.class, () -> computed.compute((Object) null), "This Optional has already been computed.");
Object otherComputedValue = new Object();
TriStateOptional<Object> empty = TriStateOptional.createNew();
empty.compute(() -> otherComputedValue);
Assertions.assertEquals(otherComputedValue, empty.get());
TriStateOptional<Object> empty2 = TriStateOptional.createNew();
empty2.compute((Object) null);
Assertions.assertTrue(empty2.isComputed());
Assertions.assertTrue(empty2.isEmpty());
}

@Test
void testIfPresent() {
TriStateOptional<Object> optional = TriStateOptional.of(new Object());
Assertions.assertThrows(RuntimeException.class, () -> optional.ifPresent(x -> {
throw new RuntimeException();
}));
TriStateOptional<Object> empty = TriStateOptional.empty();
empty.ifPresent(x -> Assertions.fail("Optional is not present!"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.github.bakedlibs.dough.data.persistent;

import be.seeseemelk.mockbukkit.persistence.PersistentDataContainerMock;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.bukkit.NamespacedKey;
import org.bukkit.persistence.PersistentDataContainer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class TestPersistentJson {

@SuppressWarnings("deprecation")
@Test
void testSerialization() {

JsonArray jsonArray = new JsonArray();
for (int i = 0; i < 100; i++) {
jsonArray.add(i);
}
JsonObject jsonObject = new JsonObject();
JsonPrimitive primitiveString = new JsonPrimitive("aString");
jsonObject.add("string", primitiveString);
PersistentDataContainer pdc = new PersistentDataContainerMock();
NamespacedKey keyString = new NamespacedKey("dummy", "string");
NamespacedKey keyArray = new NamespacedKey("dummy", "array");
pdc.set(keyString, PersistentJsonDataType.JSON_OBJECT, jsonObject);
pdc.set(keyArray, PersistentJsonDataType.JSON_ARRAY, jsonArray);

Assertions.assertTrue(pdc.has(keyString, PersistentJsonDataType.JSON_OBJECT));
JsonObject deserialized = pdc.get(keyString, PersistentJsonDataType.JSON_OBJECT);
Assertions.assertNotNull(deserialized);
Assertions.assertEquals(jsonObject, deserialized);

Assertions.assertTrue(pdc.has(keyArray, PersistentJsonDataType.JSON_ARRAY));
JsonArray deserializedArray = pdc.get(keyArray, PersistentJsonDataType.JSON_ARRAY);
Assertions.assertNotNull(deserializedArray);
Assertions.assertEquals(jsonArray, deserializedArray);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.github.bakedlibs.dough.data.persistent;

import be.seeseemelk.mockbukkit.persistence.PersistentDataContainerMock;

import org.bukkit.NamespacedKey;
import org.bukkit.persistence.PersistentDataContainer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.UUID;

class TestPersistentUUID {

@SuppressWarnings("deprecation")
@Test
void testSerialization() {
UUID uuid = UUID.randomUUID();
PersistentDataContainer pdc = new PersistentDataContainerMock();
NamespacedKey key = new NamespacedKey("dummy", "key");

pdc.set(key, PersistentUUIDDataType.TYPE, uuid);
Assertions.assertEquals(uuid, pdc.get(key, PersistentUUIDDataType.TYPE));

}

@Test
void testInvalidCases() {
Assertions.assertThrows(IllegalArgumentException.class, () -> PersistentUUIDDataType.fromIntArray(null), "The provided integer array cannot be null!");
int[] invalidData = new int[0];
Assertions.assertThrows(IllegalArgumentException.class, () -> PersistentUUIDDataType.fromIntArray(invalidData), "The integer array must have a length of 4.");
Assertions.assertThrows(IllegalArgumentException.class, () -> PersistentUUIDDataType.toIntArray(null), "The provided uuid cannot be null!");
}

@Test
void testTypeInformation() {
Assertions.assertEquals(UUID.class, PersistentUUIDDataType.TYPE.getComplexType());
Assertions.assertEquals(int[].class, PersistentUUIDDataType.TYPE.getPrimitiveType());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.github.bakedlibs.dough.data.persistent;

import be.seeseemelk.mockbukkit.persistence.PersistentDataContainerMock;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.persistence.PersistentDataContainer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class TestPersistentYAML {

@Test
@SuppressWarnings("deprecation")
void testSerialization() {
FileConfiguration configuration = new YamlConfiguration();
configuration.set("a", "b");
PersistentDataContainer pdc = new PersistentDataContainerMock();
NamespacedKey key = new NamespacedKey("dummy", "key");
pdc.set(key, PersistentYAMLDataType.CONFIG, configuration);
Assertions.assertTrue(pdc.has(key, PersistentYAMLDataType.CONFIG));
FileConfiguration deserialized = pdc.get(key, PersistentYAMLDataType.CONFIG);
Assertions.assertNotNull(deserialized);
Assertions.assertEquals("b", deserialized.get("a"));
}

@Test
void testTypeInformation() {
Assertions.assertEquals(FileConfiguration.class, PersistentYAMLDataType.CONFIG.getComplexType());
Assertions.assertEquals(String.class, PersistentYAMLDataType.CONFIG.getPrimitiveType());
}

}