diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34ac5f80379..79c7af778c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,6 +59,11 @@ jobs: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} if: ${{ env.COVERALLS_REPO_TOKEN }} run: ./gradlew test jacocoTestReport coveralls + - name: 'Game Test' + env: + GAME_TEST: ${{ secrets.GAME_TEST }} + if: ${{ env.GAME_TEST }} + run: ./gradlew runGameTestServer - name: 'Deploy as GitHub CI artifacts' uses: actions/upload-artifact@v4 with: diff --git a/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/GameTester.java b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/GameTester.java new file mode 100644 index 00000000000..fdf3fc9cae2 --- /dev/null +++ b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/GameTester.java @@ -0,0 +1,86 @@ +package org.cyclops.integrateddynamics.core.evaluate.variable.integration; + +import net.minecraft.gametest.framework.GameTestAssertException; +import net.minecraft.gametest.framework.GameTestGenerator; +import net.minecraft.gametest.framework.TestFunction; +import net.neoforged.neoforge.gametest.GameTestHolder; +import org.apache.commons.compress.utils.Lists; +import org.cyclops.integrateddynamics.Reference; +import org.cyclops.integrateddynamics.command.CommandTest; +import org.cyclops.integrateddynamics.core.test.IntegrationBefore; +import org.cyclops.integrateddynamics.core.test.IntegrationTest; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.List; + +/** + * @author rubensworks + */ +@GameTestHolder(Reference.MOD_ID) +public class GameTester { + + @GameTestGenerator + public Collection integrationTests() throws ClassNotFoundException, InstantiationException, IllegalAccessException { + List testsList = Lists.newArrayList(); + + for(String className : CommandTest.CLASSES) { + Class clazz = Class.forName(className); + Object testInstance = clazz.newInstance(); + + // Collect test methods + List befores = com.google.common.collect.Lists.newLinkedList(); + List tests = com.google.common.collect.Lists.newLinkedList(); + for(Method method : clazz.getDeclaredMethods()) { + if(method.isAnnotationPresent(IntegrationBefore.class)) { + befores.add(method); + } + if(method.isAnnotationPresent(IntegrationTest.class)) { + tests.add(method); + } + } + + // Run tests + for(Method test : tests) { + String testName = className.replace(CommandTest.P, "") + "#" + test.getName(); + + testsList.add(new TestFunction( + "defaultBatch", + testName, + "integrateddynamics:test", + 1, + 1, + true, + (gameTestHelpers) -> { + gameTestHelpers.succeedIf(() -> { + try { + for(Method before : befores) { + before.invoke(testInstance); + } + test.invoke(testInstance); + } catch (InvocationTargetException e) { + Class excepted = test.getAnnotation(IntegrationTest.class).expected(); + if(!excepted.isInstance(e.getTargetException())) { + if (e.getTargetException() instanceof IllegalStateException || e.getTargetException() instanceof AssertionError) { + e.getTargetException().printStackTrace(); + throw new GameTestAssertException("Test " + testName + " failed!"); + } else { + e.getTargetException().printStackTrace(); + throw new GameTestAssertException(String.format("Expected at %s exception %s, but found:", testName, e)); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new GameTestAssertException(e.getMessage()); + } + }); + } + )); + } + } + + return testsList; + } + +} diff --git a/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestEntityOperators.java b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestEntityOperators.java index ec3b6ccbc8f..2adfeb60945 100644 --- a/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestEntityOperators.java +++ b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestEntityOperators.java @@ -1,8 +1,11 @@ package org.cyclops.integrateddynamics.core.evaluate.variable.integration; +import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ClientInformation; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; @@ -18,6 +21,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.neoforged.neoforge.server.ServerLifecycleHooks; +import org.cyclops.cyclopscore.helper.MinecraftHelpers; import org.cyclops.integrateddynamics.api.evaluate.EvaluationException; import org.cyclops.integrateddynamics.api.evaluate.variable.IValue; import org.cyclops.integrateddynamics.api.evaluate.variable.IVariable; @@ -34,6 +38,8 @@ import org.cyclops.integrateddynamics.core.test.IntegrationTest; import org.cyclops.integrateddynamics.core.test.TestHelpers; +import java.util.UUID; + /** * Test the different logical operators. * @author rubensworks @@ -105,7 +111,16 @@ public int getUseItemRemainingTicks() { eChicken = new DummyVariableEntity(makeEntity(new Chicken(EntityType.CHICKEN, world))); eItem = new DummyVariableEntity(makeEntity(new ItemEntity(world, 0, 0, 0, ItemStack.EMPTY))); eItemFrame = new DummyVariableEntity(makeEntity(new ItemFrame(world, new BlockPos(0, 0, 0), Direction.NORTH))); - ePlayer = new DummyVariableEntity(makeEntity(world.players().get(0))); + if (MinecraftHelpers.isClientSide()) { + ePlayer = new DummyVariableEntity(makeEntity(world.players().get(0))); + } else { + ePlayer = new DummyVariableEntity(makeEntity(new ServerPlayer( + ServerLifecycleHooks.getCurrentServer(), + ServerLifecycleHooks.getCurrentServer().overworld(), + new GameProfile(UUID.randomUUID(), "test"), + ClientInformation.createDefault() + ))); + } Zombie zombieHeldItems = new Zombie(world); zombieHeldItems.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.APPLE)); zombieHeldItems.setItemSlot(EquipmentSlot.OFFHAND, new ItemStack(Items.POTATO)); diff --git a/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestVariables.java b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestVariables.java index 9d8c20703ed..dc1120d88fb 100644 --- a/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestVariables.java +++ b/src/integrationtest/java/org/cyclops/integrateddynamics/core/evaluate/variable/integration/TestVariables.java @@ -69,8 +69,8 @@ public void testIngredientsType() { itemStacks.add(serializeStack(ItemStack.EMPTY)); tag.put("minecraft:itemstack", itemStacks); - TestHelpers.assertEqual(i0.getType().serialize(ValueDeseralizationContext.ofClient(), i0.getValue()), tag, "Serialization is correct"); - TestHelpers.assertEqual(i0.getType().deserialize(ValueDeseralizationContext.ofClient(), tag), i0.getValue(), "Deserialization is correct"); + TestHelpers.assertEqual(i0.getType().serialize(ValueDeseralizationContext.ofAllEnabled(), i0.getValue()), tag, "Serialization is correct"); + TestHelpers.assertEqual(i0.getType().deserialize(ValueDeseralizationContext.ofAllEnabled(), tag), i0.getValue(), "Deserialization is correct"); } @IntegrationTest @@ -158,8 +158,8 @@ public void testRecipeType() { tag.put("input", input); tag.put("inputReusable", inputReusable); - TestHelpers.assertEqual(r0.getType().serialize(ValueDeseralizationContext.ofClient(), r0.getValue()), tag, "Serialization is correct"); - TestHelpers.assertEqual(r0.getType().deserialize(ValueDeseralizationContext.ofClient(), tag), r0.getValue(), "Deserialization is correct"); + TestHelpers.assertEqual(r0.getType().serialize(ValueDeseralizationContext.ofAllEnabled(), r0.getValue()), tag, "Serialization is correct"); + TestHelpers.assertEqual(r0.getType().deserialize(ValueDeseralizationContext.ofAllEnabled(), tag), r0.getValue(), "Deserialization is correct"); } } diff --git a/src/main/java/org/cyclops/integrateddynamics/command/CommandTest.java b/src/main/java/org/cyclops/integrateddynamics/command/CommandTest.java index faf23ebfc14..233077b6d84 100644 --- a/src/main/java/org/cyclops/integrateddynamics/command/CommandTest.java +++ b/src/main/java/org/cyclops/integrateddynamics/command/CommandTest.java @@ -25,7 +25,7 @@ */ public class CommandTest implements Command { - private static final String P = "org.cyclops.integrateddynamics.core.evaluate.variable.integration."; + public static final String P = "org.cyclops.integrateddynamics.core.evaluate.variable.integration."; public static final List CLASSES = ImmutableList.of( P + "TestVariables", P + "TestBlockOperators", diff --git a/src/main/resources/data/integrateddynamics/structure/test.nbt b/src/main/resources/data/integrateddynamics/structure/test.nbt new file mode 100644 index 00000000000..fc8fcd44956 Binary files /dev/null and b/src/main/resources/data/integrateddynamics/structure/test.nbt differ