Revert "Revert matt's changes"

This reverts commit bfcc6184ad.
This commit is contained in:
IronApollo
2020-06-13 14:41:36 -04:00
parent bfcc6184ad
commit 238c56a3c6
75 changed files with 980 additions and 687 deletions

View File

@ -0,0 +1,36 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.math;
import com.sk89q.worldedit.util.test.VariedVectors;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DisplayName("A 3D block vector")
public class BlockVector3Test {
@VariedVectors.Test(capToVanilla = true, divisionsXZ = 50, divisionsY = 50)
@DisplayName("survives a round-trip through long-packing")
void longPackingRoundTrip(BlockVector3 vec) {
assertEquals(vec, BlockVector3.fromLongPackedForm(vec.toLongPackedForm()));
}
}

View File

@ -1,133 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.sk89q.worldedit.math.BlockVector3;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.AnnotationConsumer;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
/**
* Argument provider for various vectors.
*/
public final class VariedVectorsProvider implements ArgumentsProvider, AnnotationConsumer<VariedVectorsProvider.Test> {
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ArgumentsSource(VariedVectorsProvider.class)
@ParameterizedTest(name = ParameterizedTest.ARGUMENTS_PLACEHOLDER)
public @interface Test {
/**
* If {@code true}, provide a non-matching vector from
* the existing vectors set as well. This will nearly
* square the number of tests executed, since it will
* test <em>every</em> non-matching vector.
*/
boolean provideNonMatching() default false;
}
private static final int WORLD_XZ_MINMAX = 30_000_000;
private static final long WORLD_Y_MAX = Integer.MAX_VALUE;
private static final long WORLD_Y_MIN = Integer.MIN_VALUE;
// For better coverage assurance, increase these values for a local Gradle run.
// Don't do it for IntelliJ, it'll probably run out of memory.
private static final int DIVISIONS_XZ = Integer.getInteger("variedvecs.divisions.xz", 5);
private static final int DIVISIONS_Y = Integer.getInteger("variedvecs.divisions.y", 5);
private static final int XZ_STEP = (WORLD_XZ_MINMAX * 2) / DIVISIONS_XZ;
private static final long Y_STEP = (WORLD_Y_MAX * 2) / DIVISIONS_Y;
private static final Set<BlockVector3> ALWAYS_INCLUDE =
ImmutableSet.of(BlockVector3.ZERO, BlockVector3.ONE,
BlockVector3.at(-WORLD_XZ_MINMAX, 0, -WORLD_XZ_MINMAX),
BlockVector3.at(WORLD_XZ_MINMAX, 0, WORLD_XZ_MINMAX),
BlockVector3.at(-WORLD_XZ_MINMAX, WORLD_Y_MAX, -WORLD_XZ_MINMAX),
BlockVector3.at(WORLD_XZ_MINMAX, WORLD_Y_MAX, WORLD_XZ_MINMAX));
private boolean provideNonMatching;
@Override
public void accept(Test test) {
provideNonMatching = test.provideNonMatching();
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
if (provideNonMatching) {
return makeVectorsStream()
.flatMap(vec -> makeVectorsStream().filter(v -> !v.equals(vec))
.map(v -> Arguments.of(vec, v)));
}
return makeVectorsStream().map(Arguments::of);
}
public static Stream<BlockVector3> makeVectorsStream() {
return Stream.concat(
ALWAYS_INCLUDE.stream(),
Streams.stream(generateVectors()).filter(v -> !ALWAYS_INCLUDE.contains(v))
);
}
private static Iterator<BlockVector3> generateVectors() {
return new AbstractIterator<BlockVector3>() {
private int x = -WORLD_XZ_MINMAX + 1;
private int z = -WORLD_XZ_MINMAX + 1;
private long y = WORLD_Y_MAX;
@Override
protected BlockVector3 computeNext() {
if (x > WORLD_XZ_MINMAX) {
return endOfData();
}
BlockVector3 newVector = BlockVector3.at(x, (int) y, z);
y += Y_STEP;
if (y > WORLD_Y_MAX) {
y = 0;
z += XZ_STEP;
if (z > WORLD_XZ_MINMAX) {
z = -WORLD_XZ_MINMAX;
x += XZ_STEP;
}
}
return newVector;
}
};
}
}

View File

@ -27,7 +27,8 @@ import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.Registry;
import com.sk89q.worldedit.util.VariedVectorsProvider;
import com.sk89q.worldedit.util.test.VariedVectorGenerator;
import com.sk89q.worldedit.util.test.VariedVectors;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -45,11 +46,11 @@ import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
@ -63,24 +64,23 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@DisplayName("An ordered block map")
class BlockMapTest {
/*
private static Platform mockedPlatform = mock(Platform.class);
private static final Platform MOCKED_PLATFORM = mock(Platform.class);
@BeforeAll
static void setupFakePlatform() {
when(mockedPlatform.getRegistries()).thenReturn(new BundledRegistries() {
when(MOCKED_PLATFORM.getRegistries()).thenReturn(new BundledRegistries() {
});
when(mockedPlatform.getCapabilities()).thenReturn(ImmutableMap.of(
when(MOCKED_PLATFORM.getCapabilities()).thenReturn(ImmutableMap.of(
Capability.WORLD_EDITING, Preference.PREFERRED,
Capability.GAME_HOOKS, Preference.PREFERRED
));
PlatformManager platformManager = WorldEdit.getInstance().getPlatformManager();
platformManager.register(mockedPlatform);
platformManager.register(MOCKED_PLATFORM);
registerBlock("minecraft:air");
registerBlock("minecraft:oak_wood");
@ -88,7 +88,7 @@ class BlockMapTest {
@AfterAll
static void tearDownFakePlatform() throws Exception {
WorldEdit.getInstance().getPlatformManager().unregister(mockedPlatform);
WorldEdit.getInstance().getPlatformManager().unregister(MOCKED_PLATFORM);
Field map = Registry.class.getDeclaredField("map");
map.setAccessible(true);
((Map<?, ?>) map.get(BlockType.REGISTRY)).clear();
@ -98,8 +98,6 @@ class BlockMapTest {
BlockType.REGISTRY.register(id, new BlockType(id));
}
@Mock
private Function<? super BlockVector3, ? extends BaseBlock> function;
@Mock
private BiFunction<? super BlockVector3, ? super BaseBlock, ? extends BaseBlock> biFunction;
@Mock
@ -110,7 +108,7 @@ class BlockMapTest {
private final BaseBlock air = checkNotNull(BlockTypes.AIR).getDefaultState().toBaseBlock();
private final BaseBlock oakWood = checkNotNull(BlockTypes.OAK_WOOD).getDefaultState().toBaseBlock();
private BlockMap<BaseBlock> map = BlockMap.createForBaseBlock();
private final BlockMap<BaseBlock> map = BlockMap.createForBaseBlock();
@BeforeEach
void setUp() {
@ -186,14 +184,14 @@ class BlockMapTest {
@DisplayName("never calls the forEach action")
void neverCallsForEachAction() {
map.forEach(biConsumer);
verifyZeroInteractions(biConsumer);
verifyNoMoreInteractions(biConsumer);
}
@Test
@DisplayName("never calls the replaceAll function")
void neverCallsReplaceAllFunction() {
map.replaceAll(biFunction);
verifyZeroInteractions(biFunction);
verifyNoMoreInteractions(biFunction);
}
@Test
@ -254,63 +252,62 @@ class BlockMapTest {
assertEquals(air, map.merge(BlockVector3.ZERO, air, mergeFunction));
assertEquals(1, map.size());
assertEquals(air, map.get(BlockVector3.ZERO));
verifyZeroInteractions(mergeFunction);
verifyNoMoreInteractions(mergeFunction);
}
}
@Nested
@DisplayName("after having an entry added")
@EnabledIfSystemProperty(named = "blockmap.fulltesting", matches = "true")
class AfterEntryAdded {
// Note: This section of tests would really benefit from
// being able to parameterize classes. It's not part of JUnit
// yet though: https://github.com/junit-team/junit5/issues/878
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("has a size of one")
void hasSizeOne(BlockVector3 vec) {
map.put(vec, air);
assertEquals(1, map.size());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("is equal to another map with the same entry")
void isEqualToSimilarMap(BlockVector3 vec) {
map.put(vec, air);
assertEquals(ImmutableMap.of(vec, air), map);
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("is not equal to another map with a different key")
void isNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
assertNotEquals(ImmutableMap.of(nonMatch, air), map);
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("is not equal to another map with a different value")
void isNotEqualToDifferentValueMap(BlockVector3 vec) {
map.put(vec, air);
assertNotEquals(ImmutableMap.of(vec, oakWood), map);
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("is not equal to an empty map")
void isNotEqualToEmptyMap(BlockVector3 vec) {
map.put(vec, air);
assertNotEquals(ImmutableMap.of(), map);
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("has the same hashCode as another map with the same entry")
void isHashCodeEqualToSimilarMap(BlockVector3 vec) {
map.put(vec, air);
assertEquals(ImmutableMap.of(vec, air).hashCode(), map.hashCode());
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("has a different hashCode from another map with a different key")
void isHashCodeNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) {
assumeFalse(vec.hashCode() == nonMatch.hashCode(),
@ -319,35 +316,35 @@ class BlockMapTest {
assertNotEquals(ImmutableMap.of(nonMatch, air).hashCode(), map.hashCode());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("has a different hashCode from another map with a different value")
void isHashCodeNotEqualToDifferentValueMap(BlockVector3 vec) {
map.put(vec, air);
assertNotEquals(ImmutableMap.of(vec, oakWood).hashCode(), map.hashCode());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("has a different hashCode from an empty map")
void isHashCodeNotEqualToEmptyMap(BlockVector3 vec) {
map.put(vec, air);
assertNotEquals(ImmutableMap.of().hashCode(), map.hashCode());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("returns value from get")
void returnsValueFromGet(BlockVector3 vec) {
map.put(vec, air);
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("returns `null` from get with different key")
void returnsValueFromGet(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
assertNotEquals(air, map.get(nonMatch));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("contains the key")
void containsTheKey(BlockVector3 vec) {
map.put(vec, air);
@ -356,7 +353,7 @@ class BlockMapTest {
assertTrue(map.containsKey(vec));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("contains the value")
void containsTheValue(BlockVector3 vec) {
map.put(vec, air);
@ -365,7 +362,7 @@ class BlockMapTest {
assertTrue(map.containsValue(air));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("contains the entry")
void containsTheEntry(BlockVector3 vec) {
map.put(vec, air);
@ -373,21 +370,21 @@ class BlockMapTest {
assertEquals(new AbstractMap.SimpleImmutableEntry<>(vec, air), map.entrySet().iterator().next());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("returns the provided value from getOrDefault")
void returnsProvidedFromGetOrDefault(BlockVector3 vec) {
map.put(vec, air);
assertEquals(air, map.getOrDefault(vec, oakWood));
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("returns the default value from getOrDefault with a different key")
void returnsDefaultFromGetOrDefaultWrongKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
assertEquals(oakWood, map.getOrDefault(nonMatch, oakWood));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("calls the forEach action once")
void neverCallsForEachAction(BlockVector3 vec) {
map.put(vec, air);
@ -396,7 +393,7 @@ class BlockMapTest {
verifyNoMoreInteractions(biConsumer);
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("replaces value using replaceAll")
void neverCallsReplaceAllFunction(BlockVector3 vec) {
map.put(vec, air);
@ -404,7 +401,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(vec));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("does not insert on `putIfAbsent`")
void noInsertOnPutIfAbsent(BlockVector3 vec) {
map.put(vec, air);
@ -413,7 +410,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on `putIfAbsent` to a different key")
void insertOnPutIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
@ -423,7 +420,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(nonMatch));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("remove(key) returns the old value")
void removeKeyReturnsOldValue(BlockVector3 vec) {
map.put(vec, air);
@ -431,7 +428,27 @@ class BlockMapTest {
assertEquals(0, map.size());
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test
@DisplayName("keySet().remove(key) removes the entry from the map")
void keySetRemovePassesThrough(BlockVector3 vec) {
map.put(vec, air);
assertTrue(map.keySet().remove(vec));
assertEquals(0, map.size());
}
@VariedVectors.Test
@DisplayName("entrySet().iterator().remove() removes the entry from the map")
void entrySetIteratorRemovePassesThrough(BlockVector3 vec) {
map.put(vec, air);
Iterator<Map.Entry<BlockVector3, BaseBlock>> iterator = map.entrySet().iterator();
assertTrue(iterator.hasNext());
Map.Entry<BlockVector3, BaseBlock> entry = iterator.next();
assertEquals(entry.getKey(), vec);
iterator.remove();
assertEquals(0, map.size());
}
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("remove(nonMatch) returns null")
void removeNonMatchingKeyReturnsNull(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
@ -439,7 +456,7 @@ class BlockMapTest {
assertEquals(1, map.size());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("remove(key, value) returns true")
void removeKeyValueReturnsTrue(BlockVector3 vec) {
map.put(vec, air);
@ -447,7 +464,7 @@ class BlockMapTest {
assertEquals(0, map.size());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("remove(key, value) returns false for wrong value")
void removeKeyValueReturnsFalseWrongValue(BlockVector3 vec) {
map.put(vec, air);
@ -455,7 +472,7 @@ class BlockMapTest {
assertEquals(1, map.size());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("replaces value at key")
void replacesValueAtKey(BlockVector3 vec) {
map.put(vec, air);
@ -469,7 +486,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("does not replace value at different key")
void doesNotReplaceAtDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
@ -483,7 +500,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("does not insert on computeIfAbsent")
void doesNotInsertComputeIfAbsent(BlockVector3 vec) {
map.put(vec, air);
@ -495,7 +512,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on computeIfAbsent with different key")
void insertsOnComputeIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
@ -508,7 +525,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(nonMatch));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("replaces on compute")
void replaceOnCompute(BlockVector3 vec) {
map.put(vec, air);
@ -523,7 +540,7 @@ class BlockMapTest {
assertEquals(0, map.size());
}
@VariedVectorsProvider.Test(provideNonMatching = true)
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on compute with different key")
void insertOnComputeDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air);
@ -540,7 +557,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec));
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("replaces on computeIfPresent")
void replacesOnComputeIfPresent(BlockVector3 vec) {
map.put(vec, air);
@ -555,7 +572,7 @@ class BlockMapTest {
assertEquals(0, map.size());
}
@VariedVectorsProvider.Test
@VariedVectors.Test
@DisplayName("inserts on merge, with call to merge function")
void insertsOnMerge(BlockVector3 vec) {
map.put(vec, air);
@ -573,7 +590,9 @@ class BlockMapTest {
@Test
@DisplayName("contains all inserted vectors")
void containsAllInsertedVectors() {
Set<BlockVector3> allVectors = VariedVectorsProvider.makeVectorsStream().collect(Collectors.toSet());
Set<BlockVector3> allVectors = new VariedVectorGenerator()
.makeVectorsStream()
.collect(Collectors.toSet());
for (BlockVector3 vec : allVectors) {
map.put(vec, air);
}

View File

@ -0,0 +1,98 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.collection;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.test.VariedVectors;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
abstract class PositionListTest {
static class Long extends PositionListTest {
protected Long() {
super(new LongPositionList());
}
}
static class Vector extends PositionListTest {
protected Vector() {
super(new VectorPositionList());
}
}
private final PositionList positionList;
protected PositionListTest(PositionList positionList) {
this.positionList = positionList;
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling add(vec) increases size by 1")
void addIncreasesSizeByOne(BlockVector3 vec) {
positionList.add(vec);
assertEquals(1, positionList.size());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling get(0) after add(vec) returns vec")
void canGetVectorAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.get(0));
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling iterator().hasNext() after add(vec) returns true")
void hasNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertTrue(positionList.iterator().hasNext());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling iterator().next() after add(vec) returns vec")
void nextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.iterator().next());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling reverseIterator().hasNext() after add(vec) returns true")
void reverseHasNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertTrue(positionList.reverseIterator().hasNext());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling reverseIterator().next() after add(vec) returns vec")
void reverseNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.reverseIterator().next());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling clear() after add(vec) makes the size() zero")
void clearAfterAdd(BlockVector3 vec) {
positionList.add(vec);
positionList.clear();
assertEquals(0, positionList.size());
}
}

View File

@ -0,0 +1,100 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.test;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.sk89q.worldedit.math.BlockVector3;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
public class VariedVectorGenerator {
// For better coverage assurance, increase these values for a local Gradle run.
// Don't do it for IntelliJ, it'll probably run out of memory.
private static final int DEFAULT_DIVISIONS_XZ =
Integer.getInteger("variedvecs.divisions.xz", 5);
private static final int DEFAULT_DIVISIONS_Y =
Integer.getInteger("variedvecs.divisions.y", 5);
public final int divisionsXZ;
public final int divisionsY;
public final int maxXZ;
public final long maxY;
public final int xzStep;
public final long yStep;
public final Set<BlockVector3> alwaysInclude;
public VariedVectorGenerator() {
this(false, -1, -1);
}
public VariedVectorGenerator(boolean vanilla, int divisionsXZ, int divisionsY) {
this.divisionsXZ = divisionsXZ == -1 ? DEFAULT_DIVISIONS_XZ : divisionsXZ;
this.divisionsY = divisionsY == -1 ? DEFAULT_DIVISIONS_Y : divisionsY;
maxXZ = 30_000_000;
maxY = vanilla ? 255 : Integer.MAX_VALUE;
xzStep = (maxXZ * 2) / this.divisionsXZ;
yStep = (maxY * 2) / this.divisionsY;
alwaysInclude =
ImmutableSet.of(BlockVector3.ZERO, BlockVector3.ONE,
BlockVector3.at(-maxXZ, 0, -maxXZ),
BlockVector3.at(maxXZ, 0, maxXZ),
BlockVector3.at(-maxXZ, maxY, -maxXZ),
BlockVector3.at(maxXZ, maxY, maxXZ));
}
public Stream<BlockVector3> makeVectorsStream() {
return Stream.concat(
alwaysInclude.stream(),
Streams.stream(generateVectors()).filter(v -> !alwaysInclude.contains(v))
);
}
private Iterator<BlockVector3> generateVectors() {
return new AbstractIterator<BlockVector3>() {
private int x = -maxXZ + 1;
private int z = -maxXZ + 1;
private long y = maxY;
@Override
protected BlockVector3 computeNext() {
if (x > maxXZ) {
return endOfData();
}
BlockVector3 newVector = BlockVector3.at(x, (int) y, z);
y += yStep;
if (y > maxY) {
y = 0;
z += xzStep;
if (z > maxXZ) {
z = -maxXZ;
x += xzStep;
}
}
return newVector;
}
};
}
}

View File

@ -0,0 +1,87 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.AnnotationConsumer;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.stream.Stream;
/**
* Argument provider for various vectors.
*/
public final class VariedVectors implements ArgumentsProvider, AnnotationConsumer<VariedVectors.Test> {
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ArgumentsSource(VariedVectors.class)
@ParameterizedTest(name = ParameterizedTest.ARGUMENTS_PLACEHOLDER)
public @interface Test {
/**
* If {@code true}, provide a non-matching vector from
* the existing vectors set as well. This will nearly
* square the number of tests executed, since it will
* test <em>every</em> non-matching vector.
*/
boolean provideNonMatching() default false;
/**
* If {@code true}, only provide vectors inside the range of Vanilla MC.
* This caps the Y value to 255.
*/
boolean capToVanilla() default false;
int divisionsXZ() default -1;
int divisionsY() default -1;
}
private boolean provideNonMatching;
private VariedVectorGenerator generator;
@Override
public void accept(Test test) {
provideNonMatching = test.provideNonMatching();
generator = new VariedVectorGenerator(test.capToVanilla(), test.divisionsXZ(), test.divisionsY());
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
if (provideNonMatching) {
return generator.makeVectorsStream()
.flatMap(vec -> generator.makeVectorsStream().filter(v -> !v.equals(vec))
.map(v -> Arguments.of(vec, v)));
}
return generator.makeVectorsStream().map(Arguments::of);
}
}