#1473: Change tests to use suites, to run tests in different environments and feature flags

This commit is contained in:
DerFrZocker 2024-09-26 20:01:56 +10:00 committed by md_5
parent d25e1e7225
commit e4c92ef65b
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
85 changed files with 1012 additions and 302 deletions

View File

@ -67,6 +67,10 @@ Code Requirements
Bukkit/CraftBukkit employs [JUnit 5](https://www.vogella.com/tutorials/JUnit/article.html) for testing. Pull Requests(PR) should attempt to integrate within that framework as appropriate.
Bukkit is a large project and what seems simple to a PR author at the time of writing may easily be overlooked by other authors and updates. Including unit tests with your PR
will help to ensure the PR can be easily maintained over time and encourage the Spigot team to pull the PR.
CraftBukkit provides multiple environments for testing, which init the server to various states.
Each test **needs** to have an environment, either by setting it to the whole class or the individual test methods.
A test can have multiple environments.
You can see the available test environments in [src/test/java/org.bukkit.support.environment](src/test/java/org/bukkit/support/environment).
* There needs to be a new line at the end of every file.
* Imports should be organised in a logical manner.

13
pom.xml
View File

@ -10,6 +10,7 @@
<properties>
<skipTests>true</skipTests>
<groups>AllFeatures,Bundle,Legacy,Normal,VanillaFeature</groups>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<api.version>unknown</api.version>
<bt.name>git</bt.name>
@ -274,6 +275,11 @@
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-engine</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
@ -487,9 +493,10 @@
<version>3.2.5</version>
<configuration>
<workingDirectory>${basedir}/target/test-server</workingDirectory>
<excludes>
<exclude>org/bukkit/craftbukkit/inventory/ItemStack*Test.java</exclude>
</excludes>
<reuseForks>false</reuseForks>
<includes>
<include>**/*TestSuite.java</include>
</includes>
</configuration>
</plugin>
</plugins>

View File

@ -15,10 +15,11 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.world.entity.decoration.PaintingVariant;
import org.bukkit.craftbukkit.CraftArt;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class ArtTest extends AbstractTestingBase {
@AllFeatures
public class ArtTest {
@Test
public void verifyMapping() {

View File

@ -1,13 +1,16 @@
package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.biome.BiomeBase;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class BiomeTest extends AbstractTestingBase {
@AllFeatures
public class BiomeTest {
@Test
public void testBukkitToMinecraft() {
@ -22,7 +25,7 @@ public class BiomeTest extends AbstractTestingBase {
@Test
public void testMinecraftToBukkit() {
for (BiomeBase biomeBase : BIOMES) {
for (BiomeBase biomeBase : CraftRegistry.getMinecraftRegistry(Registries.BIOME)) {
Biome biome = CraftBiome.minecraftToBukkit(biomeBase);
assertTrue(biome != null && biome != Biome.CUSTOM, "No Bukkit mapping for " + biomeBase);
}

View File

@ -6,7 +6,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@ -15,7 +15,8 @@ import org.junit.jupiter.params.provider.MethodSource;
* This test class ensures that all Blocks (as registered in BuiltInRegistries.BLOCK)
* can be converted into their CraftBlockData equivalent.
*/
public class BlockDataConversionTest extends AbstractTestingBase {
@AllFeatures
public class BlockDataConversionTest {
public static Stream<Arguments> data() {
return BuiltInRegistries.BLOCK.stream().map(Block::defaultBlockState).map(Arguments::of);

View File

@ -13,10 +13,11 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Cake;
import org.bukkit.block.data.type.Chest;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
public class BlockDataTest extends AbstractTestingBase {
@VanillaFeature
public class BlockDataTest {
@Test
public void testParsing() {

View File

@ -4,10 +4,11 @@ import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.EnumChatFormat;
import net.minecraft.network.chat.IChatBaseComponent;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
public class ChatTest extends AbstractTestingBase {
@VanillaFeature
public class ChatTest {
@Test
public void testColors() {

View File

@ -3,11 +3,12 @@ package org.bukkit;
import static org.bukkit.support.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import net.minecraft.world.item.EnumColor;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
public class DyeColorsTest extends AbstractTestingBase {
@Normal
public class DyeColorsTest {
@ParameterizedTest
@EnumSource(DyeColor.class)

View File

@ -6,10 +6,11 @@ import net.minecraft.resources.MinecraftKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class EnchantmentTest extends AbstractTestingBase {
@AllFeatures
public class EnchantmentTest {
@Test
public void verifyMapping() {

View File

@ -3,10 +3,11 @@ package org.bukkit;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.core.registries.BuiltInRegistries;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class GameEventTest extends AbstractTestingBase {
@AllFeatures
public class GameEventTest {
@Test
public void toBukkit() {

View File

@ -4,8 +4,10 @@ import static org.junit.jupiter.api.Assertions.*;
import java.util.Map;
import net.minecraft.world.level.GameRules;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class GameRuleTest {
@Test

View File

@ -5,10 +5,11 @@ import net.minecraft.resources.ResourceKey;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.LootTables;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class LootTablesTest extends AbstractTestingBase {
@AllFeatures
public class LootTablesTest {
@Test
public void testLootTablesEnumExists() {

View File

@ -16,16 +16,18 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.item.Item;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.LegacyHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class MaterialTest extends AbstractTestingBase {
@AllFeatures
public class MaterialTest {
@Test
public void verifyMapping() {
Map<MinecraftKey, Material> materials = Maps.newHashMap();
for (Material material : Material.values()) {
if (INVALIDATED_MATERIALS.contains(material)) {
if (LegacyHelper.getInvalidatedMaterials().contains(material)) {
continue;
}

View File

@ -26,7 +26,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.junit.jupiter.params.ParameterizedTest;
@ -34,7 +34,8 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
public class ParticleTest extends AbstractTestingBase {
@AllFeatures
public class ParticleTest {
public static Stream<Arguments> data() {
return CraftRegistry.getMinecraftRegistry(Registries.PARTICLE_TYPE).keySet().stream().map(Arguments::of);

View File

@ -28,12 +28,14 @@ import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.LegacyHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
public class PerMaterialTest extends AbstractTestingBase {
@AllFeatures
public class PerMaterialTest {
private static Map<Block, Integer> fireValues;
@BeforeAll
@ -84,7 +86,7 @@ public class PerMaterialTest extends AbstractTestingBase {
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void maxDurability(Material material) {
if (INVALIDATED_MATERIALS.contains(material)) return;
if (LegacyHelper.getInvalidatedMaterials().contains(material)) return;
if (material == Material.AIR) {
assertThat((int) material.getMaxDurability(), is(0));
@ -97,7 +99,7 @@ public class PerMaterialTest extends AbstractTestingBase {
@ParameterizedTest
@EnumSource(value = Material.class, names = "LEGACY_.*", mode = EnumSource.Mode.MATCH_NONE)
public void maxStackSize(Material material) {
if (INVALIDATED_MATERIALS.contains(material)) return;
if (LegacyHelper.getInvalidatedMaterials().contains(material)) return;
final ItemStack bukkit = new ItemStack(material);
final CraftItemStack craft = CraftItemStack.asCraftCopy(bukkit);

View File

@ -13,10 +13,11 @@ import org.bukkit.craftbukkit.potion.CraftPotionEffectTypeCategory;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionEffectTypeCategory;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class PotionEffectTypeTest extends AbstractTestingBase {
@AllFeatures
public class PotionEffectTypeTest {
@Test
public void verifyMapping() {

View File

@ -7,10 +7,11 @@ import java.util.Locale;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.MinecraftKey;
import org.bukkit.craftbukkit.CraftSound;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class SoundTest extends AbstractTestingBase {
@AllFeatures
public class SoundTest {
@Test
public void testGetSound() {

View File

@ -9,10 +9,11 @@ import net.minecraft.stats.StatisticWrapper;
import net.minecraft.world.entity.EntityTypes;
import org.bukkit.craftbukkit.CraftStatistic;
import org.bukkit.entity.EntityType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class StatisticsAndAchievementsTest extends AbstractTestingBase {
@AllFeatures
public class StatisticsAndAchievementsTest {
@Test
@SuppressWarnings("unchecked")

View File

@ -8,10 +8,11 @@ import net.minecraft.world.level.block.entity.EnumBannerPatternType;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class PatternTypeTest extends AbstractTestingBase {
@AllFeatures
public class PatternTypeTest {
@Test
public void testToBukkit() {

View File

@ -2,8 +2,10 @@ package org.bukkit.craftbukkit;
import static org.junit.jupiter.api.Assertions.*;
import org.bukkit.HeightMap;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class HeightMapTest {
@Test

View File

@ -5,10 +5,11 @@ import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.entity.ai.attributes.AttributeBase;
import org.bukkit.attribute.Attribute;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class AttributeTest extends AbstractTestingBase {
@AllFeatures
public class AttributeTest {
@Test
public void testToBukkit() {

View File

@ -7,10 +7,11 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.ITileEntity;
import net.minecraft.world.level.block.entity.TileEntity;
import org.bukkit.Material;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class BlockStateTest extends AbstractTestingBase {
@AllFeatures
public class BlockStateTest {
@Test
public void testTileEntityBlockStates() {

View File

@ -4,8 +4,10 @@ import static org.bukkit.support.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import java.lang.reflect.Field;
import org.bukkit.block.BlockType;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class BlockTypeTest {
// Ensures all BlockType constants have the correct generics

View File

@ -56,7 +56,7 @@ import org.bukkit.entity.ThrowableProjectile;
import org.bukkit.entity.TippedArrow;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.WaterMob;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
@ -64,7 +64,8 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
public class EntityTypesTest extends AbstractTestingBase {
@AllFeatures
public class EntityTypesTest {
private static final URI BUKKIT_CLASSES;
// Entity classes, which do not have any entity type / entity type data

View File

@ -3,10 +3,12 @@ package org.bukkit.craftbukkit.generator;
import static org.junit.jupiter.api.Assertions.*;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.RegistryHelper;
import org.bukkit.support.environment.Legacy;
import org.junit.jupiter.api.Test;
public class ChunkDataTest extends AbstractTestingBase {
@Legacy
public class ChunkDataTest {
private static final BlockData RED_WOOL = Material.RED_WOOL.createBlockData();
private static final BlockData AIR = Material.AIR.createBlockData();
@ -34,21 +36,21 @@ public class ChunkDataTest extends AbstractTestingBase {
@Test
public void testMinHeight() {
OldCraftChunkData data = new OldCraftChunkData(-128, 128, BIOMES);
OldCraftChunkData data = new OldCraftChunkData(-128, 128, RegistryHelper.getBiomes());
assertTrue(testSetBlock(data, 0, -256, 0, RED_WOOL, AIR), "Could not set block below min height");
assertTrue(testSetBlock(data, 0, -64, 0, RED_WOOL, RED_WOOL), "Could set block above min height");
}
@Test
public void testMaxHeight() {
OldCraftChunkData data = new OldCraftChunkData(0, 128, BIOMES);
OldCraftChunkData data = new OldCraftChunkData(0, 128, RegistryHelper.getBiomes());
assertTrue(testSetBlock(data, 0, 128, 0, RED_WOOL, AIR), "Could not set block above max height");
assertTrue(testSetBlock(data, 0, 127, 0, RED_WOOL, RED_WOOL), "Could set block below max height");
}
@Test
public void testBoundsCheckingSingle() {
OldCraftChunkData data = new OldCraftChunkData(0, 256, BIOMES);
OldCraftChunkData data = new OldCraftChunkData(0, 256, RegistryHelper.getBiomes());
assertTrue(testSetBlock(data, 0, 0, 0, RED_WOOL, RED_WOOL), "Can set block inside chunk bounds");
assertTrue(testSetBlock(data, 15, 255, 15, RED_WOOL, RED_WOOL), "Can set block inside chunk bounds");
assertTrue(testSetBlock(data, -1, 0, 0, RED_WOOL, AIR), "Can no set block outside chunk bounds");
@ -61,7 +63,7 @@ public class ChunkDataTest extends AbstractTestingBase {
@Test
public void testSetRegion() {
OldCraftChunkData data = new OldCraftChunkData(0, 256, BIOMES);
OldCraftChunkData data = new OldCraftChunkData(0, 256, RegistryHelper.getBiomes());
testSetRegion(data, -100, 0, -100, 0, 256, 0, RED_WOOL); // exclusively outside
testSetRegion(data, 16, 256, 16, 0, 0, 0, RED_WOOL); // minimum >= maximum
testSetRegion(data, 0, 0, 0, 0, 0, 0, RED_WOOL); // minimum == maximum

View File

@ -12,10 +12,11 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
public class CompositeSerialization extends AbstractTestingBase {
@Normal
public class CompositeSerialization {
public YamlConfiguration getConfig() {
return new YamlConfiguration();

View File

@ -16,11 +16,12 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
import org.bukkit.inventory.meta.tags.ItemTagAdapterContext;
import org.bukkit.inventory.meta.tags.ItemTagType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Legacy;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class DeprecatedItemMetaCustomValueTest extends AbstractTestingBase {
@Legacy
public class DeprecatedItemMetaCustomValueTest {
private static NamespacedKey VALID_KEY;

View File

@ -10,14 +10,16 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.LegacyHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@AllFeatures
@EnabledIfSystemProperty(named = "testEnv", matches = "full", disabledReason = "Disable for now, since Mockito's Location feature is too heavy in combination with this test")
public class FactoryItemMaterialTest extends AbstractTestingBase {
public class FactoryItemMaterialTest {
static final ItemFactory factory = CraftItemFactory.instance();
static final StringBuilder buffer = new StringBuilder();
static final Material[] materials;
@ -26,7 +28,7 @@ public class FactoryItemMaterialTest extends AbstractTestingBase {
Material[] local_materials = Material.values();
List<Material> list = new ArrayList<Material>(local_materials.length);
for (Material material : local_materials) {
if (INVALIDATED_MATERIALS.contains(material)) {
if (LegacyHelper.getInvalidatedMaterials().contains(material)) {
continue;
}

View File

@ -5,8 +5,10 @@ import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.reflect.Method;
import org.bukkit.Material;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
@AllFeatures
public class ItemMetaCloneTest {
@Test

View File

@ -10,10 +10,12 @@ import java.util.stream.Stream;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.Overridden;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@AllFeatures
public class ItemMetaImplementationOverrideTest {
static final Class<CraftMetaItem> parent = CraftMetaItem.class;

View File

@ -61,10 +61,11 @@ import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
public class ItemMetaTest extends AbstractTestingBase {
@VanillaFeature
public class ItemMetaTest {
static final int MAX_FIREWORK_POWER = 255; // Please update ItemStackFireworkTest if/when this gets changed.

View File

@ -21,7 +21,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import org.junit.jupiter.params.ParameterizedTest;
@ -29,7 +29,8 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
public class ItemStackTest extends AbstractTestingBase {
@AllFeatures
public class ItemStackTest {
abstract static class StackProvider {
final Material material;

View File

@ -13,11 +13,12 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.trim.ArmorTrim;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class ItemTypeTest extends AbstractTestingBase {
@AllFeatures
public class ItemTypeTest {
// Ensures all ItemType constants have the correct generics
@Test

View File

@ -5,10 +5,11 @@ import static org.hamcrest.Matchers.*;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
public class NMSCraftItemStackTest extends AbstractTestingBase {
@VanillaFeature
public class NMSCraftItemStackTest {
@Test
public void testCloneEnchantedItem() throws Exception {

View File

@ -24,7 +24,7 @@ import org.bukkit.persistence.ListPersistentDataType;
import org.bukkit.persistence.PersistentDataAdapterContext;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -33,7 +33,8 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class PersistentDataContainerTest extends AbstractTestingBase {
@AllFeatures
public class PersistentDataContainerTest {
private static NamespacedKey VALID_KEY;

View File

@ -4,10 +4,11 @@ import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.world.entity.player.PlayerInventory;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
public class PlayerInventoryTest extends AbstractTestingBase {
@Normal
public class PlayerInventoryTest {
@Test
public void testCanHold() throws Exception {

View File

@ -2,10 +2,11 @@ package org.bukkit.craftbukkit.legacy;
import static org.junit.jupiter.api.Assertions.*;
import org.bukkit.Material;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Legacy;
import org.junit.jupiter.api.Test;
public class EvilTest extends AbstractTestingBase {
@Legacy
public class EvilTest {
@Test
public void testFrom() {

View File

@ -7,10 +7,11 @@ import java.util.Set;
import org.bukkit.Material;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.material.MaterialData;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Legacy;
import org.junit.jupiter.api.Test;
public class LegacyTest extends AbstractTestingBase {
@Legacy
public class LegacyTest {
private final Set<Material> INVALIDATED_MATERIALS = new HashSet<>(Arrays.asList(Material.ACACIA_BUTTON, Material.ACACIA_PRESSURE_PLATE, Material.ACACIA_TRAPDOOR, Material.AIR, Material.ATTACHED_MELON_STEM, Material.ATTACHED_PUMPKIN_STEM,
Material.BIRCH_BUTTON, Material.BIRCH_PRESSURE_PLATE, Material.BIRCH_TRAPDOOR, Material.BLACK_WALL_BANNER, Material.BLUE_WALL_BANNER, Material.BROWN_WALL_BANNER, Material.BUBBLE_COLUMN, Material.CAVE_AIR, Material.CREEPER_WALL_HEAD,

View File

@ -18,7 +18,7 @@ import org.bukkit.craftbukkit.legacy.reroute.RerouteBuilder;
import org.bukkit.craftbukkit.legacy.reroute.RerouteMethodData;
import org.bukkit.craftbukkit.util.ApiVersion;
import org.bukkit.craftbukkit.util.Commodore;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
@ -29,7 +29,8 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
public class MaterialReroutingTest extends AbstractTestingBase {
@Normal
public class MaterialReroutingTest {
// Needs to be a bukkit class
private static final URI BUKKIT_CLASSES;

View File

@ -13,10 +13,11 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Legacy;
import org.junit.jupiter.api.Test;
public class PersistentDataContainerLegacyTest extends AbstractTestingBase {
@Legacy
public class PersistentDataContainerLegacyTest {
@Test
public void ensureLegacyParsing() {

View File

@ -9,11 +9,13 @@ import java.util.Map;
import java.util.stream.Stream;
import org.bukkit.craftbukkit.legacy.reroute.RerouteMethodData;
import org.bukkit.craftbukkit.util.Commodore;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.objectweb.asm.Type;
@Normal
public class RerouteValidationTest {
public static Stream<Arguments> data() {

View File

@ -14,8 +14,10 @@ import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.profile.PlayerTextures;
import org.bukkit.support.condition.EnableIfMojangServerAvailable;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class PlayerProfileTest {
/*

View File

@ -3,13 +3,14 @@ package org.bukkit.craftbukkit.util;
import static org.junit.jupiter.api.Assertions.*;
import java.util.stream.Stream;
import net.minecraft.SharedConstants;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.VanillaFeature;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class ApiVersionTest extends AbstractTestingBase {
@VanillaFeature
public class ApiVersionTest {
public static Stream<Arguments> parseData() {
return Stream.of(

View File

@ -4,8 +4,10 @@ import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.chat.IChatMutableComponent;
import net.minecraft.network.chat.contents.LiteralContents;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class CraftChatMessageTest {
@Test

View File

@ -2,8 +2,10 @@ package org.bukkit.damage;
import static org.junit.jupiter.api.Assertions.*;
import org.bukkit.craftbukkit.damage.CraftDamageType;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class DamageTypeTest {
@Test

View File

@ -2,10 +2,11 @@ package org.bukkit.entity;
import net.minecraft.world.entity.vehicle.EntityBoat;
import org.bukkit.craftbukkit.entity.CraftBoat;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
public class BoatTest extends AbstractTestingBase {
@Normal
public class BoatTest {
@Test
public void testTypes() {

View File

@ -3,8 +3,10 @@ package org.bukkit.entity;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.world.entity.boss.enderdragon.phases.DragonControllerPhase;
import org.bukkit.craftbukkit.entity.CraftEnderDragon;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class EnderDragonPhaseTest {
@Test

View File

@ -2,8 +2,10 @@ package org.bukkit.entity;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.world.entity.EntityPose;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class EntityPoseTest {
@Test

View File

@ -7,10 +7,11 @@ import java.util.stream.Collectors;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.world.entity.EntityTypes;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class EntityTypesTest extends AbstractTestingBase {
@AllFeatures
public class EntityTypesTest {
@Test
public void testMaps() {

View File

@ -3,8 +3,10 @@ package org.bukkit.entity;
import static org.junit.jupiter.api.Assertions.*;
import net.minecraft.world.entity.animal.EntityPanda;
import org.bukkit.craftbukkit.entity.CraftPanda;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class PandaGeneTest {
@Test

View File

@ -2,8 +2,10 @@ package org.bukkit.entity;
import net.minecraft.world.entity.EnumCreatureType;
import org.bukkit.craftbukkit.util.CraftSpawnCategory;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class SpawnCategoryTest {
@Test

View File

@ -5,8 +5,10 @@ import static org.hamcrest.Matchers.*;
import org.bukkit.DyeColor;
import org.bukkit.craftbukkit.entity.CraftTropicalFish;
import org.bukkit.entity.TropicalFish.Pattern;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.Test;
@Normal
public class TropicalFishTest {
@Test

View File

@ -6,11 +6,12 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class CraftMemoryKeyTest extends AbstractTestingBase {
@AllFeatures
public class CraftMemoryKeyTest {
@Test
public void shouldConvertBukkitHomeKeyToNMSRepresentation() {

View File

@ -18,7 +18,7 @@ import java.util.stream.Stream;
import net.minecraft.WorldVersion;
import net.minecraft.server.Main;
import net.minecraft.world.level.entity.EntityAccess;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
@ -34,7 +34,8 @@ import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
public class EntityRemoveEventTest extends AbstractTestingBase {
@Normal
public class EntityRemoveEventTest {
// Needs to be a class, which is present in the source, and not a test class
private static final URI CRAFT_BUKKIT_CLASSES;

View File

@ -9,11 +9,13 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class StructureTest extends AbstractTestingBase {
@AllFeatures
public class StructureTest {
@Test
public void testBukkitToMinecraftFieldName() {
@ -32,7 +34,7 @@ public class StructureTest extends AbstractTestingBase {
@Test
public void testMinecraftToBukkitFieldName() {
IRegistry<net.minecraft.world.level.levelgen.structure.Structure> structureBuiltInRegistries = AbstractTestingBase.REGISTRY_CUSTOM.registryOrThrow(Registries.STRUCTURE);
IRegistry<net.minecraft.world.level.levelgen.structure.Structure> structureBuiltInRegistries = CraftRegistry.getMinecraftRegistry(Registries.STRUCTURE);
for (net.minecraft.world.level.levelgen.structure.Structure structure : structureBuiltInRegistries) {
MinecraftKey minecraftKey = structureBuiltInRegistries.getKey(structure);

View File

@ -5,14 +5,17 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Locale;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class StructureTypeTest extends AbstractTestingBase {
@AllFeatures
public class StructureTypeTest {
@Test
public void testBukkitToMinecraftFieldName() {
@ -31,7 +34,7 @@ public class StructureTypeTest extends AbstractTestingBase {
@Test
public void testMinecraftToBukkitFieldName() {
for (net.minecraft.world.level.levelgen.structure.StructureType<?> structureType : BuiltInRegistries.STRUCTURE_TYPE) {
for (net.minecraft.world.level.levelgen.structure.StructureType<?> structureType : CraftRegistry.getMinecraftRegistry(Registries.STRUCTURE_TYPE)) {
MinecraftKey minecraftKey = BuiltInRegistries.STRUCTURE_TYPE.getKey(structureType);
try {

View File

@ -7,7 +7,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.world.level.material.MaterialMapColor;
import org.bukkit.craftbukkit.map.CraftMapColorCache;
import org.junit.jupiter.api.Disabled;
import org.bukkit.support.environment.Normal;
import org.bukkit.support.environment.Slow;
import org.junit.jupiter.api.Test;
public class MapTest {
@ -17,6 +18,7 @@ public class MapTest {
private static final int[] modifiers = {180, 220, 255, 135};
@Test
@Normal
public void testColors() {
MaterialMapColor[] nmsColors = MaterialMapColor.MATERIAL_COLORS;
Color[] bukkitColors = MapPalette.colors;
@ -62,8 +64,8 @@ public class MapTest {
assertFalse(fail);
}
@Disabled("Test takes around 25 seconds, should be run by changes to the map color conversion")
@Test
@Slow("Test takes around 25 seconds, should be run by changes to the map color conversion")
public void testMapColorCacheBuilding() throws ExecutionException, InterruptedException {
CraftMapColorCache craftMapColorCache = new CraftMapColorCache(logger);
craftMapColorCache.initCache().get();

View File

@ -11,10 +11,11 @@ import net.minecraft.world.effect.MobEffectList;
import net.minecraft.world.item.alchemy.PotionRegistry;
import org.bukkit.craftbukkit.legacy.FieldRename;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class PotionTest extends AbstractTestingBase {
@AllFeatures
public class PotionTest {
@Test
public void testEffectCompleteness() throws Throwable {
Map<PotionType, String> effects = new EnumMap(PotionType.class);

View File

@ -10,13 +10,14 @@ import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class PerRegistryTest extends AbstractTestingBase {
@AllFeatures
public class PerRegistryTest {
private static Random random;

View File

@ -5,8 +5,8 @@ import com.google.common.base.Joiner;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Registry;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.DummyServer;
import org.bukkit.support.environment.AllFeatures;
import org.bukkit.support.extension.AllFeaturesExtension;
import org.bukkit.support.provider.RegistriesArgumentProvider;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.provider.Arguments;
@ -14,14 +14,15 @@ import org.junit.jupiter.params.provider.Arguments;
/**
* This class tests, if all default registries present in {@link Registry} are added to {@link RegistriesArgumentProvider}
*/
public class RegistryArgumentAddedTest extends AbstractTestingBase {
@AllFeatures
public class RegistryArgumentAddedTest {
@Test
public void testPresent() throws ClassNotFoundException {
// Make sure every registry is created
Class.forName(Registry.class.getName());
Set<Class<?>> loadedRegistries = new HashSet<>(DummyServer.registers.keySet());
Set<Class<?>> loadedRegistries = new HashSet<>(AllFeaturesExtension.getRealRegistries().keySet());
Set<Class<?>> notFound = new HashSet<>();
RegistriesArgumentProvider

View File

@ -17,10 +17,12 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.damage.DamageType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.RegistryHelper;
import org.bukkit.support.environment.AllFeatures;
import org.junit.jupiter.api.Test;
public class RegistryConstantsTest extends AbstractTestingBase {
@AllFeatures
public class RegistryConstantsTest {
@Test
public void testDamageType() {
@ -62,7 +64,7 @@ public class RegistryConstantsTest extends AbstractTestingBase {
private <T extends Keyed, M> void testMissingConstants(Class<T> clazz, ResourceKey<IRegistry<M>> nmsRegistryKey) {
List<MinecraftKey> missingKeys = new ArrayList<>();
IRegistry<M> nmsRegistry = REGISTRY_CUSTOM.registryOrThrow(nmsRegistryKey);
IRegistry<M> nmsRegistry = RegistryHelper.getRegistry().registryOrThrow(nmsRegistryKey);
for (M nmsObject : nmsRegistry) {
MinecraftKey minecraftKey = nmsRegistry.getKey(nmsObject);

View File

@ -17,7 +17,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.AllFeatures;
import org.bukkit.support.provider.RegistryArgumentProvider;
import org.bukkit.support.test.RegistriesTest;
import org.junit.jupiter.api.MethodOrderer;
@ -25,8 +25,9 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.provider.Arguments;
@AllFeatures
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegistryConversionTest extends AbstractTestingBase {
public class RegistryConversionTest {
private static final String MINECRAFT_TO_BUKKIT = "minecraftToBukkit";
private static final String BUKKIT_TO_MINECRAFT = "bukkitToMinecraft";

View File

@ -15,13 +15,14 @@ import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.AbstractTestingBase;
import org.bukkit.support.environment.Normal;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class RegistryLoadOrderTest extends AbstractTestingBase {
@Normal
public class RegistryLoadOrderTest {
private static boolean initInterface = false;
private static boolean initAbstract = false;

View File

@ -1,77 +0,0 @@
package org.bukkit.support;
import static org.junit.jupiter.api.Assertions.*;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandDispatcher;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryDataLoader;
import net.minecraft.server.DataPackResources;
import net.minecraft.server.DispenserRegistry;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.packs.EnumResourcePackType;
import net.minecraft.server.packs.repository.ResourcePackLoader;
import net.minecraft.server.packs.repository.ResourcePackRepository;
import net.minecraft.server.packs.repository.ResourcePackSourceVanilla;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.biome.BiomeBase;
import org.bukkit.Material;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
/**
* If you are getting: java.lang.ExceptionInInitializerError
* at net.minecraft.server.StatisticList.&lt;clinit&gt;(SourceFile:58)
* at net.minecraft.server.Item.&lt;clinit&gt;(SourceFile:252)
* at net.minecraft.server.Block.&lt;clinit&gt;(Block.java:577)
*
* extend this class to solve it.
*/
public abstract class AbstractTestingBase {
// Materials that only exist in block form (or are legacy)
public static final List<Material> INVALIDATED_MATERIALS;
public static final DataPackResources DATA_PACK;
public static final IRegistryCustom.Dimension REGISTRY_CUSTOM;
public static final IRegistry<BiomeBase> BIOMES;
static {
SharedConstants.tryDetectVersion();
DispenserRegistry.bootStrap();
// Populate available packs
ResourcePackRepository resourceRepository = ResourcePackSourceVanilla.createVanillaTrustedRepository();
resourceRepository.reload();
// Set up resource manager
ResourceManager resourceManager = new ResourceManager(EnumResourcePackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().map(ResourcePackLoader::open).toList());
// add tags and loot tables for unit tests
LayeredRegistryAccess<RegistryLayer> layers = RegistryLayer.createRegistryAccess();
layers = WorldLoader.loadAndReplaceLayer(resourceManager, layers, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES);
REGISTRY_CUSTOM = layers.compositeAccess().freeze();
// Register vanilla pack
DATA_PACK = DataPackResources.loadResources(resourceManager, layers, FeatureFlags.REGISTRY.allFlags(), CommandDispatcher.ServerType.DEDICATED, 0, MoreExecutors.directExecutor(), MoreExecutors.directExecutor()).join();
// Bind tags
DATA_PACK.updateRegistryTags();
// Biome shortcut
BIOMES = REGISTRY_CUSTOM.registryOrThrow(Registries.BIOME);
DummyServer.setup();
CraftRegistry.setMinecraftRegistry(REGISTRY_CUSTOM);
ImmutableList.Builder<Material> builder = ImmutableList.builder();
for (Material m : Material.values()) {
if (m.isLegacy() || CraftMagicNumbers.getItem(m) == null) {
builder.add(m);
}
}
INVALIDATED_MATERIALS = builder.build();
assertEquals(610, INVALIDATED_MATERIALS.size(), "Expected 610 invalidated materials (got " + INVALIDATED_MATERIALS.size() + ")");
}
}

View File

@ -1,114 +0,0 @@
package org.bukkit.support;
import static org.mockito.Mockito.*;
import com.google.common.base.Preconditions;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.tag.CraftBlockTag;
import org.bukkit.craftbukkit.tag.CraftEntityTag;
import org.bukkit.craftbukkit.tag.CraftFluidTag;
import org.bukkit.craftbukkit.tag.CraftItemTag;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.Versioning;
import org.mockito.stubbing.Answer;
public final class DummyServer {
public static final Map<Class<?>, Registry<?>> registers = new HashMap<>();
static {
try {
Server instance = mock(withSettings().stubOnly());
when(instance.getItemFactory()).thenAnswer(mock -> CraftItemFactory.instance());
when(instance.getName()).thenReturn(DummyServer.class.getName());
when(instance.getVersion()).thenReturn(DummyServer.class.getPackage().getImplementationVersion());
when(instance.getBukkitVersion()).thenReturn(Versioning.getBukkitVersion());
when(instance.getLogger()).thenReturn(Logger.getLogger(DummyServer.class.getCanonicalName()));
when(instance.getUnsafe()).then(mock -> CraftMagicNumbers.INSTANCE);
when(instance.createBlockData(any(Material.class))).then(mock -> CraftBlockData.newData(((Material) mock.getArgument(0)).asBlockType(), null));
when(instance.getLootTable(any())).then(mock -> new CraftLootTable(mock.getArgument(0),
AbstractTestingBase.DATA_PACK.fullRegistries().getLootTable(ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(mock.getArgument(0))))));
when(instance.getRegistry(any())).then((Answer<Registry<?>>) mock -> {
Class<? extends Keyed> aClass = mock.getArgument(0);
return registers.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, AbstractTestingBase.REGISTRY_CUSTOM));
});
when(instance.getTag(any(), any(), any())).then(mock -> {
String registry = mock.getArgument(0);
Class<?> clazz = mock.getArgument(2);
MinecraftKey key = CraftNamespacedKey.toMinecraft(mock.getArgument(1));
switch (registry) {
case org.bukkit.Tag.REGISTRY_BLOCKS -> {
Preconditions.checkArgument(clazz == org.bukkit.Material.class, "Block namespace must have block type");
TagKey<Block> blockTagKey = TagKey.create(Registries.BLOCK, key);
if (BuiltInRegistries.BLOCK.getTag(blockTagKey).isPresent()) {
return new CraftBlockTag(BuiltInRegistries.BLOCK, blockTagKey);
}
}
case org.bukkit.Tag.REGISTRY_ITEMS -> {
Preconditions.checkArgument(clazz == org.bukkit.Material.class, "Item namespace must have item type");
TagKey<Item> itemTagKey = TagKey.create(Registries.ITEM, key);
if (BuiltInRegistries.ITEM.getTag(itemTagKey).isPresent()) {
return new CraftItemTag(BuiltInRegistries.ITEM, itemTagKey);
}
}
case org.bukkit.Tag.REGISTRY_FLUIDS -> {
Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type");
TagKey<FluidType> fluidTagKey = TagKey.create(Registries.FLUID, key);
if (BuiltInRegistries.FLUID.getTag(fluidTagKey).isPresent()) {
return new CraftFluidTag(BuiltInRegistries.FLUID, fluidTagKey);
}
}
case org.bukkit.Tag.REGISTRY_ENTITY_TYPES -> {
Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity type namespace must have entity type");
TagKey<EntityTypes<?>> entityTagKey = TagKey.create(Registries.ENTITY_TYPE, key);
if (BuiltInRegistries.ENTITY_TYPE.getTag(entityTagKey).isPresent()) {
return new CraftEntityTag(BuiltInRegistries.ENTITY_TYPE, entityTagKey);
}
}
default -> throw new IllegalArgumentException();
}
return null;
});
Bukkit.setServer(instance);
} catch (Throwable t) {
throw new Error(t);
}
}
public static void setup() {}
private DummyServer() {};
}

View File

@ -0,0 +1,92 @@
package org.bukkit.support;
import static org.mockito.Mockito.*;
import com.google.common.base.Preconditions;
import java.util.logging.Logger;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftLootTable;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.tag.CraftBlockTag;
import org.bukkit.craftbukkit.tag.CraftEntityTag;
import org.bukkit.craftbukkit.tag.CraftFluidTag;
import org.bukkit.craftbukkit.tag.CraftItemTag;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.Versioning;
public final class DummyServerHelper {
public static Server setup() {
Server instance = mock(withSettings().stubOnly());
when(instance.getItemFactory()).thenAnswer(mock -> CraftItemFactory.instance());
when(instance.getName()).thenReturn(DummyServerHelper.class.getName());
when(instance.getVersion()).thenReturn(DummyServerHelper.class.getPackage().getImplementationVersion());
when(instance.getBukkitVersion()).thenReturn(Versioning.getBukkitVersion());
when(instance.getLogger()).thenReturn(Logger.getLogger(DummyServerHelper.class.getCanonicalName()));
when(instance.getUnsafe()).then(mock -> CraftMagicNumbers.INSTANCE);
when(instance.createBlockData(any(Material.class))).then(mock -> CraftBlockData.newData(((Material) mock.getArgument(0)).asBlockType(), null));
when(instance.getLootTable(any())).then(mock -> new CraftLootTable(mock.getArgument(0),
RegistryHelper.getDataPack().fullRegistries().getLootTable(ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(mock.getArgument(0))))));
when(instance.getTag(any(), any(), any())).then(mock -> {
String registry = mock.getArgument(0);
Class<?> clazz = mock.getArgument(2);
MinecraftKey key = CraftNamespacedKey.toMinecraft(mock.getArgument(1));
switch (registry) {
case org.bukkit.Tag.REGISTRY_BLOCKS -> {
Preconditions.checkArgument(clazz == Material.class, "Block namespace must have block type");
TagKey<Block> blockTagKey = TagKey.create(Registries.BLOCK, key);
if (BuiltInRegistries.BLOCK.getTag(blockTagKey).isPresent()) {
return new CraftBlockTag(BuiltInRegistries.BLOCK, blockTagKey);
}
}
case org.bukkit.Tag.REGISTRY_ITEMS -> {
Preconditions.checkArgument(clazz == Material.class, "Item namespace must have item type");
TagKey<Item> itemTagKey = TagKey.create(Registries.ITEM, key);
if (BuiltInRegistries.ITEM.getTag(itemTagKey).isPresent()) {
return new CraftItemTag(BuiltInRegistries.ITEM, itemTagKey);
}
}
case org.bukkit.Tag.REGISTRY_FLUIDS -> {
Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type");
TagKey<FluidType> fluidTagKey = TagKey.create(Registries.FLUID, key);
if (BuiltInRegistries.FLUID.getTag(fluidTagKey).isPresent()) {
return new CraftFluidTag(BuiltInRegistries.FLUID, fluidTagKey);
}
}
case org.bukkit.Tag.REGISTRY_ENTITY_TYPES -> {
Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity type namespace must have entity type");
TagKey<EntityTypes<?>> entityTagKey = TagKey.create(Registries.ENTITY_TYPE, key);
if (BuiltInRegistries.ENTITY_TYPE.getTag(entityTagKey).isPresent()) {
return new CraftEntityTag(BuiltInRegistries.ENTITY_TYPE, entityTagKey);
}
}
default -> throw new IllegalArgumentException();
}
return null;
});
return instance;
}
}

View File

@ -0,0 +1,29 @@
package org.bukkit.support;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
public final class LegacyHelper {
// Materials that only exist in block form (or are legacy)
private static final List<Material> INVALIDATED_MATERIALS;
static {
ImmutableList.Builder<Material> builder = ImmutableList.builder();
for (Material m : Material.values()) {
if (m.isLegacy() || CraftMagicNumbers.getItem(m) == null) {
builder.add(m);
}
}
INVALIDATED_MATERIALS = builder.build();
}
private LegacyHelper() {
}
public static List<Material> getInvalidatedMaterials() {
return INVALIDATED_MATERIALS;
}
}

View File

@ -0,0 +1,111 @@
package org.bukkit.support;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.Locale;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandDispatcher;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryDataLoader;
import net.minecraft.server.DataPackResources;
import net.minecraft.server.DispenserRegistry;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.packs.EnumResourcePackType;
import net.minecraft.server.packs.repository.ResourcePackLoader;
import net.minecraft.server.packs.repository.ResourcePackRepository;
import net.minecraft.server.packs.repository.ResourcePackSourceVanilla;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.level.biome.BiomeBase;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
public final class RegistryHelper {
private static DataPackResources dataPack;
private static IRegistryCustom.Dimension registry;
private static IRegistry<BiomeBase> biomes;
private RegistryHelper() {
}
public static DataPackResources getDataPack() {
if (dataPack == null) {
throwError("dataPack");
}
return dataPack;
}
public static IRegistryCustom.Dimension getRegistry() {
if (registry == null) {
throwError("registry");
}
return registry;
}
public static IRegistry<BiomeBase> getBiomes() {
if (biomes == null) {
throwError("biomes");
}
return biomes;
}
public static IRegistryCustom.Dimension createRegistry(FeatureFlagSet featureFlagSet) {
return createLayers(createResourceManager(featureFlagSet)).compositeAccess().freeze();
}
public static void setup(FeatureFlagSet featureFlagSet) {
SharedConstants.tryDetectVersion();
DispenserRegistry.bootStrap();
ResourceManager resourceManager = createResourceManager(featureFlagSet);
LayeredRegistryAccess<RegistryLayer> layers = createLayers(resourceManager);
registry = layers.compositeAccess().freeze();
// Register vanilla pack
dataPack = DataPackResources.loadResources(resourceManager, layers, featureFlagSet, CommandDispatcher.ServerType.DEDICATED, 0, MoreExecutors.directExecutor(), MoreExecutors.directExecutor()).join();
// Bind tags
dataPack.updateRegistryTags();
// Biome shortcut
biomes = registry.registryOrThrow(Registries.BIOME);
}
public static <T extends Keyed> Class<T> updateClass(Class<T> aClass, NamespacedKey key) {
Class<T> theClass;
// Some registries have extra Typed classes such as BlockType and ItemType.
// To avoid class cast exceptions during init mock the Typed class.
// To get the correct class, we just use the field type.
try {
theClass = (Class<T>) aClass.getField(key.getKey().toUpperCase(Locale.ROOT).replace('.', '_')).getType();
} catch (ClassCastException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
return theClass;
}
private static ResourceManager createResourceManager(FeatureFlagSet featureFlagSet) {
// Populate available packs
ResourcePackRepository resourceRepository = ResourcePackSourceVanilla.createVanillaTrustedRepository();
resourceRepository.reload();
// Set up resource manager
return new ResourceManager(EnumResourcePackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().filter(pack -> pack.getRequestedFeatures().isSubsetOf(featureFlagSet)).map(ResourcePackLoader::open).toList());
}
private static LayeredRegistryAccess<RegistryLayer> createLayers(ResourceManager resourceManager) {
// add tags and loot tables for unit tests
LayeredRegistryAccess<RegistryLayer> layers = RegistryLayer.createRegistryAccess();
layers = WorldLoader.loadAndReplaceLayer(resourceManager, layers, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES);
return layers;
}
private static void throwError(String field) {
throw new IllegalStateException(String.format("""
Trying to access %s will it is not setup.
Make sure that either the class or method you test has the right test environment annotation present.
You can find them in the package src/test/java/org.bukkit.support.environment""", field));
}
}

View File

@ -0,0 +1,19 @@
package org.bukkit.support.environment;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.bukkit.support.extension.AllFeaturesExtension;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Indicates that a class or method should be tested with all Minecraft feature flags set.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Tag("AllFeatures")
@ExtendWith({AllFeaturesExtension.class})
public @interface AllFeatures {
}

View File

@ -0,0 +1,19 @@
package org.bukkit.support.environment;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.bukkit.support.extension.LegacyExtension;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Indicates that a class or method tests legacy behavior and requires some legacy initialization.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Tag("Legacy")
@ExtendWith({LegacyExtension.class})
public @interface Legacy {
}

View File

@ -0,0 +1,21 @@
package org.bukkit.support.environment;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.bukkit.support.extension.NormalExtension;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Indicates that a class or method is an independent test and does not require direct access to registry values.
* To allow loading of classes with registry values,
* they are populated with mocks that will throw an error if accessed.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Tag("Normal")
@ExtendWith({NormalExtension.class})
public @interface Normal {
}

View File

@ -0,0 +1,24 @@
package org.bukkit.support.environment;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.bukkit.support.extension.SlowExtension;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Indicates that a class or method is a slow test, which takes a longer time to complete.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Tag("Slow")
@ExtendWith({SlowExtension.class})
public @interface Slow {
/**
* The reason / estimated time to complete, this is purely for documentation.
*/
String value() default "";
}

View File

@ -0,0 +1,19 @@
package org.bukkit.support.environment;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.bukkit.support.extension.VanillaFeatureExtension;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* Indicates that a class or method should be tested with Minecraft's vanilla feature flag set.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Tag("VanillaFeature")
@ExtendWith({VanillaFeatureExtension.class})
public @interface VanillaFeature {
}

View File

@ -0,0 +1,65 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
import org.bukkit.support.RegistryHelper;
import org.junit.jupiter.api.extension.ExtensionContext;
public class AllFeaturesExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> realRegistries = new HashMap<>();
private static final Map<Class<? extends Keyed>, Registry<?>> spyRegistries = new HashMap<>();
public AllFeaturesExtension() {
super("AllFeatures");
}
public static <T extends Keyed> Registry<T> getRealRegistry(Class<T> clazz) {
return (Registry<T>) realRegistries.get(clazz);
}
public static Map<Class<? extends Keyed>, Registry<?>> getRealRegistries() {
return realRegistries;
}
@Override
public void init(ExtensionContext extensionContext) {
RegistryHelper.setup(FeatureFlags.REGISTRY.allFlags());
Server server = DummyServerHelper.setup();
Bukkit.setServer(server);
when(server.getRegistry(any()))
.then(invocation -> {
Class<? extends Keyed> keyed = invocation.getArgument(0);
if (spyRegistries.containsKey(keyed)) {
return spyRegistries.get(keyed);
}
Registry<?> registry = CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry());
realRegistries.put(keyed, registry);
Registry<?> spy = mock(registry.getClass(), withSettings().stubOnly().spiedInstance(registry).defaultAnswer(CALLS_REAL_METHODS));
spyRegistries.put(keyed, spy);
return spy;
});
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
@Override
void runBeforeEach(ExtensionContext extensionContext) {
}
}

View File

@ -0,0 +1,109 @@
package org.bukkit.support.extension;
import static org.junit.jupiter.api.Assertions.*;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Logger;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
public abstract class BaseExtension implements BeforeAllCallback, BeforeEachCallback {
private static final Set<String> IGNORE_TAGS = Sets.newHashSet();
private static String currentlyRunning = null;
private static boolean run = false;
protected final Logger logger;
private final String testSuite;
public BaseExtension(String testSuite) {
this.testSuite = testSuite;
this.logger = Logger.getLogger(testSuite);
}
@Override
public final void beforeAll(ExtensionContext extensionContext) throws Exception {
if (!isTestCase(extensionContext)) {
return;
}
checkRunBeforeOnce(extensionContext);
}
@Override
public final void beforeEach(ExtensionContext extensionContext) throws Exception {
if (!isTestCase(extensionContext)) {
return;
}
checkRunBeforeOnce(extensionContext);
runBeforeEach(extensionContext);
}
private boolean isTestCase(ExtensionContext extensionContext) {
if (currentlyRunning != null) {
return testSuite.equals(currentlyRunning);
}
Optional<String> runningTestSuite = extensionContext.getConfigurationParameter("TestSuite");
if (runningTestSuite.isPresent()) {
// We are inside a test suite, check if it is the test suite from this extension
if (!runningTestSuite.get().equals(testSuite)) {
return false;
}
currentlyRunning = testSuite;
logger.info("Running tests with environment: " + testSuite);
return true;
}
Set<String> tags = new HashSet<>(extensionContext.getTags());
tags.removeAll(IGNORE_TAGS);
if (!tags.contains(testSuite)) {
fail(String.format("""
Extension was triggered without the tag for the test suite being present. This should not happen.
Did you forget to add @Tag to a new environment annotation? Or maybe a spelling mistake?
Expected %s, but found:
%s""", testSuite, Joiner.on('\n').join(tags)));
return false; // Will never reach ):
}
if (tags.size() >= 2) {
fail((String.format("""
Found more than one tag present in test case %s.
Will it is possible to run a test in multiple environments, this is only possible when running the test via a test suite,
otherwise it is not possible to distinguish which environment should get loaded.
To run a test standalone please temporary comment out the environments which should not be run, so that only one is present.
If only one is set and you still see this message make sure that every tag which is not for selecting environments,
is added to the org.bukkit.support.extension.BaseExtension#IGNORE_TAGS set.
Also note, that class level environments have a higher priority then method level environments.
Following multiple tags are present:
%s""", extensionContext.getDisplayName(), Joiner.on('\n').join(tags))));
return false; // Will never reach ):
}
currentlyRunning = testSuite;
logger.info("Running tests with environment: " + testSuite);
return true;
}
private void checkRunBeforeOnce(ExtensionContext extensionContext) {
if (run) {
return;
}
init(extensionContext);
run = true;
}
abstract void init(ExtensionContext extensionContext);
abstract void runBeforeEach(ExtensionContext extensionContext);
}

View File

@ -0,0 +1,45 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
import org.bukkit.support.RegistryHelper;
import org.junit.jupiter.api.extension.ExtensionContext;
public class LegacyExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public LegacyExtension() {
super("Legacy");
}
@Override
public void init(ExtensionContext extensionContext) {
RegistryHelper.setup(FeatureFlags.VANILLA_SET);
Server server = DummyServerHelper.setup();
Bukkit.setServer(server);
when(server.getRegistry(any()))
.then(invocation -> {
Class<? extends Keyed> keyed = invocation.getArgument(0);
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
});
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
@Override
void runBeforeEach(ExtensionContext extensionContext) {
}
}

View File

@ -0,0 +1,69 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
import org.bukkit.support.RegistryHelper;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.mockito.stubbing.Answer;
public class NormalExtension extends BaseExtension {
private static final Answer<?> DEFAULT_ANSWER = invocation -> {
throw new UnsupportedOperationException("""
Cannot use registry operation during normal testing.
Either change the code so that it does no longer need registry for testing,
or use another testing environment, such as @VanillaFeature or @AllFeatures.
""");
};
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public NormalExtension() {
super("Normal");
}
@Override
public void init(ExtensionContext extensionContext) {
RegistryHelper.setup(FeatureFlags.VANILLA_SET);
Server server = DummyServerHelper.setup();
Bukkit.setServer(server);
when(server.getRegistry(any()))
.then(invocation -> {
Class<? extends Keyed> keyed = invocation.getArgument(0);
return registries.computeIfAbsent(keyed, k -> createMockBukkitRegistry(keyed));
});
IRegistryCustom registry = mock(withSettings().stubOnly().defaultAnswer(DEFAULT_ANSWER));
CraftRegistry.setMinecraftRegistry(registry);
}
@Override
void runBeforeEach(ExtensionContext extensionContext) {
}
private <T extends Keyed> Registry<T> createMockBukkitRegistry(Class<T> keyed) {
Map<NamespacedKey, T> mocks = new HashMap<>();
Registry<T> registry = mock(withSettings().stubOnly().defaultAnswer(DEFAULT_ANSWER));
doAnswer(invocation ->
mocks.computeIfAbsent(invocation.getArgument(0), k -> mock(RegistryHelper.updateClass(keyed, invocation.getArgument(0)), withSettings().stubOnly().defaultAnswer(DEFAULT_ANSWER)))
).when(registry).get(any()); // Allow static classes to fill there fields, so that it does not error out, just by loading them
return registry;
}
}

View File

@ -0,0 +1,45 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
import org.bukkit.support.RegistryHelper;
import org.junit.jupiter.api.extension.ExtensionContext;
public class SlowExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public SlowExtension() {
super("Slow");
}
@Override
public void init(ExtensionContext extensionContext) {
RegistryHelper.setup(FeatureFlags.VANILLA_SET);
Server server = DummyServerHelper.setup();
Bukkit.setServer(server);
when(server.getRegistry(any()))
.then(invocation -> {
Class<? extends Keyed> keyed = invocation.getArgument(0);
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
});
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
@Override
void runBeforeEach(ExtensionContext extensionContext) {
}
}

View File

@ -0,0 +1,45 @@
package org.bukkit.support.extension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.world.flag.FeatureFlags;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.support.DummyServerHelper;
import org.bukkit.support.RegistryHelper;
import org.junit.jupiter.api.extension.ExtensionContext;
public class VanillaFeatureExtension extends BaseExtension {
private static final Map<Class<? extends Keyed>, Registry<?>> registries = new HashMap<>();
public VanillaFeatureExtension() {
super("VanillaFeature");
}
@Override
public void init(ExtensionContext extensionContext) {
RegistryHelper.setup(FeatureFlags.VANILLA_SET);
Server server = DummyServerHelper.setup();
Bukkit.setServer(server);
when(server.getRegistry(any()))
.then(invocation -> {
Class<? extends Keyed> keyed = invocation.getArgument(0);
return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
});
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
@Override
void runBeforeEach(ExtensionContext extensionContext) {
}
}

View File

@ -0,0 +1,17 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.ExcludeClassNamePatterns;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for test which need registry values present, with all feature flags set")
@IncludeTags("AllFeatures")
@SelectPackages("org.bukkit")
@ExcludeClassNamePatterns("org.bukkit.craftbukkit.inventory.ItemStack.*Test")
@ConfigurationParameter(key = "TestSuite", value = "AllFeatures")
public class AllFeaturesTestSuite {
}

View File

@ -0,0 +1,15 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for test which need registry values present, with the bundle feature flag set")
@IncludeTags("BundleFeature")
@SelectPackages("org.bukkit")
@ConfigurationParameter(key = "TestSuite", value = "BundleFeature")
public class BundleFeatureTestSuite {
}

View File

@ -0,0 +1,15 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for legacy tests")
@IncludeTags("Legacy")
@SelectPackages("org.bukkit")
@ConfigurationParameter(key = "TestSuite", value = "Legacy")
public class LegacyTestSuite {
}

View File

@ -0,0 +1,15 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for standalone tests, which don't need any registry values present")
@IncludeTags("Normal")
@SelectPackages("org.bukkit")
@ConfigurationParameter(key = "TestSuite", value = "Normal")
public class NormalTestSuite {
}

View File

@ -0,0 +1,15 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for slow tests, which don't need to run every time")
@IncludeTags("Slow")
@SelectPackages("org.bukkit")
@ConfigurationParameter(key = "TestSuite", value = "Slow")
public class SlowTestSuite {
}

View File

@ -0,0 +1,15 @@
package org.bukkit.support.suite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeTags;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite(failIfNoTests = false)
@SuiteDisplayName("Test suite for test which need vanilla registry values present")
@IncludeTags("VanillaFeature")
@SelectPackages("org.bukkit")
@ConfigurationParameter(key = "TestSuite", value = "VanillaFeature")
public class VanillaFeatureTestSuite {
}