-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* start on implementing tests. * add slim jar for publishing. * it almost works :lets: * my test cases broke :waaGONE:
- Loading branch information
Showing
16 changed files
with
458 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
common/src/main/java/com/gregtechceu/gtceu/test/GTGameTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.gregtechceu.gtceu.test; | ||
|
||
import appeng.server.testworld.PlotTestHelper; | ||
import com.gregtechceu.gtceu.GTCEu; | ||
import com.gregtechceu.gtceu.test.api.machine.trait.ParallelLogicTest; | ||
import com.gregtechceu.gtceu.test.api.machine.trait.RecipeLogicTest; | ||
import com.gregtechceu.gtceu.utils.FormattingUtil; | ||
import com.mojang.datafixers.util.Pair; | ||
import com.simibubi.create.infrastructure.gametest.CreateTestFunction; | ||
import com.simibubi.create.infrastructure.gametest.tests.*; | ||
import io.github.fabricators_of_create.porting_lib.gametest.infrastructure.ExtendedTestFunction; | ||
import net.minecraft.gametest.framework.GameTest; | ||
import net.minecraft.gametest.framework.GameTestGenerator; | ||
import net.minecraft.gametest.framework.GameTestRegistry; | ||
import net.minecraft.gametest.framework.TestFunction; | ||
import net.minecraft.world.level.block.Rotation; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Modifier; | ||
import java.util.Collection; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.function.Consumer; | ||
import java.util.stream.Stream; | ||
|
||
public class GTGameTests { | ||
private static final Class<?>[] testHolders = { | ||
RecipeLogicTest.class, | ||
ParallelLogicTest.class | ||
}; | ||
|
||
@GameTestGenerator | ||
public static Collection<TestFunction> generateTests() { | ||
return getTestsFrom(testHolders); | ||
} | ||
|
||
public static Collection<TestFunction> getTestsFrom(Class<?>... classes) { | ||
return Stream.of(classes) | ||
.map(Class::getDeclaredMethods) | ||
.flatMap(Stream::of) | ||
.filter(method -> !method.isSynthetic() && method.getAnnotation(GameTest.class) != null) | ||
.map(method -> Pair.of(method, method.getAnnotation(GameTest.class))) | ||
.map(method -> new TestFunction( | ||
"gtceu", | ||
GTCEu.MOD_ID + "." + method.getFirst().getDeclaringClass().getSimpleName() + "." + method.getFirst().getName(), | ||
method.getSecond().template(), | ||
Rotation.NONE, | ||
method.getSecond().timeoutTicks(), | ||
method.getSecond().setupTicks(), | ||
method.getSecond().required(), | ||
method.getSecond().requiredSuccesses(), | ||
method.getSecond().attempts(), | ||
gameTestHelper -> { | ||
try { | ||
Object object = null; | ||
if (!Modifier.isStatic(method.getFirst().getModifiers())) { | ||
object = method.getFirst().getDeclaringClass().getConstructor().newInstance(); | ||
} | ||
method.getFirst().invoke(object, gameTestHelper); | ||
} catch (ReflectiveOperationException e) { | ||
throw new RuntimeException(e); | ||
} | ||
})) | ||
.sorted(Comparator.comparing(TestFunction::getTestName)) | ||
.toList(); | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
common/src/main/java/com/gregtechceu/gtceu/test/api/machine/trait/ParallelLogicTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.gregtechceu.gtceu.test.api.machine.trait; | ||
|
||
import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; | ||
import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability; | ||
import com.gregtechceu.gtceu.api.capability.recipe.IO; | ||
import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; | ||
import com.gregtechceu.gtceu.api.machine.MetaMachine; | ||
import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; | ||
import com.gregtechceu.gtceu.api.recipe.GTRecipe; | ||
import com.gregtechceu.gtceu.common.data.GTMaterials; | ||
import com.gregtechceu.gtceu.common.data.GTRecipeModifiers; | ||
import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; | ||
import com.lowdragmc.lowdraglib.side.fluid.IFluidTransfer; | ||
import com.lowdragmc.lowdraglib.side.item.IItemTransfer; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.gametest.framework.GameTest; | ||
import net.minecraft.gametest.framework.GameTestHelper; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.level.block.Blocks; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
|
||
public class ParallelLogicTest { | ||
|
||
@GameTest(template = "gtceu:ebf") | ||
public void getMaxRecipeMultiplier_FluidLimitTest(GameTestHelper helper) { | ||
BlockEntity holder = helper.getBlockEntity(new BlockPos(1, 1, 0)); | ||
if (!(holder instanceof MetaMachineBlockEntity atte)) { | ||
helper.fail("wrong block at relative pos [1,1,0]!"); | ||
return; | ||
} | ||
MetaMachine machine = atte.getMetaMachine(); | ||
if (!(machine instanceof IRecipeLogicMachine rlm)) { | ||
helper.fail("wrong machine in MetaMachineBlockEntity!"); | ||
return; | ||
} | ||
|
||
int parallelLimit = 4; | ||
|
||
// Create a simple recipe to be used for testing | ||
GTRecipe recipe = GTRecipeBuilder.ofRaw() | ||
.inputItems(new ItemStack(Blocks.COBBLESTONE)) | ||
.inputFluids(GTMaterials.Acetone.getFluid(4000)) | ||
.outputItems(new ItemStack(Blocks.STONE)) | ||
.blastFurnaceTemp(1000) | ||
.EUt(30).duration(100) | ||
.buildRawRecipe(); | ||
|
||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP)).insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); | ||
((IFluidTransfer)rlm.getCapabilitiesProxy().get(IO.IN, FluidRecipeCapability.CAP)).fill(GTMaterials.Acetone.getFluid(8000), false); | ||
|
||
var paralleled = GTRecipeModifiers.accurateParallel(machine, recipe, parallelLimit, false); | ||
|
||
helper.assertTrue(paralleled.getB() == 2,"Expected Parallel amount to be 2, is %s.".formatted(paralleled.getB())); | ||
|
||
helper.succeed(); | ||
} | ||
|
||
@GameTest(template = "gtceu:ebf") | ||
public void getMaxRecipeMultiplier_LimitFailureTest(GameTestHelper helper) { | ||
BlockEntity holder = helper.getBlockEntity(new BlockPos(1, 1, 0)); | ||
if (!(holder instanceof MetaMachineBlockEntity atte)) { | ||
helper.fail("wrong block at relative pos [1,1,0]!"); | ||
return; | ||
} | ||
MetaMachine machine = atte.getMetaMachine(); | ||
if (!(machine instanceof IRecipeLogicMachine rlm)) { | ||
helper.fail("wrong machine in MetaMachineBlockEntity!"); | ||
return; | ||
} | ||
|
||
int parallelLimit = 4; | ||
|
||
// Create a simple recipe to be used for testing | ||
GTRecipe recipe = GTRecipeBuilder.ofRaw() | ||
.inputItems(new ItemStack(Blocks.COBBLESTONE)) | ||
.inputFluids(GTMaterials.Acetone.getFluid(1000)) | ||
.outputItems(new ItemStack(Blocks.STONE)) | ||
.blastFurnaceTemp(1000) | ||
.EUt(30).duration(100) | ||
.buildRawRecipe(); | ||
|
||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP)).insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); | ||
((IFluidTransfer)rlm.getCapabilitiesProxy().get(IO.IN, FluidRecipeCapability.CAP)).fill(GTMaterials.Acetone.getFluid(8000), false); | ||
|
||
var paralleled = GTRecipeModifiers.accurateParallel(machine, recipe, parallelLimit, false); | ||
|
||
helper.assertTrue(paralleled == null || paralleled.getB() == 0, "Parallel is too high, should be 0, is %s.".formatted(paralleled.getB())); | ||
|
||
helper.succeed(); | ||
} | ||
|
||
@GameTest(template = "gtceu:ebf") | ||
public void getMaxRecipeMultiplier_ItemFailureTest(GameTestHelper helper) { | ||
BlockEntity holder = helper.getBlockEntity(new BlockPos(1, 1, 0)); | ||
if (!(holder instanceof MetaMachineBlockEntity atte)) { | ||
helper.fail("wrong block at relative pos [1,1,0]!"); | ||
return; | ||
} | ||
MetaMachine machine = atte.getMetaMachine(); | ||
if (!(machine instanceof IRecipeLogicMachine rlm)) { | ||
helper.fail("wrong machine in MetaMachineBlockEntity!"); | ||
return; | ||
} | ||
|
||
int parallelLimit = 4; | ||
|
||
// Create a simple recipe to be used for testing | ||
GTRecipe recipe = GTRecipeBuilder.ofRaw() | ||
.inputItems(new ItemStack(Blocks.COBBLESTONE)) | ||
.inputFluids(GTMaterials.Acetone.getFluid(100)) | ||
.outputItems(new ItemStack(Blocks.STONE)) | ||
.blastFurnaceTemp(1000) | ||
.EUt(30).duration(100) | ||
.buildRawRecipe(); | ||
|
||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP)).insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); | ||
((IFluidTransfer)rlm.getCapabilitiesProxy().get(IO.IN, FluidRecipeCapability.CAP)).fill(GTMaterials.Naphtha.getFluid(8000), false); | ||
|
||
var paralleled = GTRecipeModifiers.accurateParallel(machine, recipe, parallelLimit, false); | ||
|
||
helper.assertTrue(paralleled == null || paralleled.getB() == 0, "Parallel is too high, should be 0, is %s.".formatted(paralleled.getB())); | ||
|
||
helper.succeed(); | ||
} | ||
|
||
// TODO add the rest of https://github.com/GregTechCEu/GregTech/blob/master/src/test/java/gregtech/api/recipes/logic/ParallelLogicTest.java. | ||
} |
114 changes: 114 additions & 0 deletions
114
common/src/main/java/com/gregtechceu/gtceu/test/api/machine/trait/RecipeLogicTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package com.gregtechceu.gtceu.test.api.machine.trait; | ||
|
||
import com.gregtechceu.gtceu.GTCEu; | ||
import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; | ||
import com.gregtechceu.gtceu.api.capability.recipe.IO; | ||
import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; | ||
import com.gregtechceu.gtceu.api.machine.MetaMachine; | ||
import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; | ||
import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; | ||
import com.gregtechceu.gtceu.api.recipe.GTRecipe; | ||
import com.gregtechceu.gtceu.common.data.GTRecipeTypes; | ||
import com.gregtechceu.gtceu.core.mixins.RecipeManagerAccessor; | ||
import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; | ||
import com.lowdragmc.lowdraglib.side.item.IItemTransfer; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.gametest.framework.BeforeBatch; | ||
import net.minecraft.gametest.framework.GameTest; | ||
import net.minecraft.gametest.framework.GameTestHelper; | ||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.level.block.Blocks; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
|
||
import java.util.HashMap; | ||
|
||
public class RecipeLogicTest { | ||
|
||
private static boolean hasInjectedRecipe = false; | ||
|
||
@BeforeBatch(batch = GTCEu.MOD_ID) | ||
public static void replaceRecipeManagerEntries(ServerLevel level) { | ||
if (hasInjectedRecipe) return; | ||
var recipes = new HashMap<>(((RecipeManagerAccessor) level.getRecipeManager()).getRawRecipes()); | ||
((RecipeManagerAccessor)level.getRecipeManager()).setRawRecipes(recipes); | ||
recipes.replaceAll((k, v) -> new HashMap<>(v)); | ||
} | ||
|
||
@GameTest(template = "gtceu:recipelogic") | ||
public static void recipeLogicTest(GameTestHelper helper) { | ||
// oops the BeforeBatch isn't registered. | ||
RecipeLogicTest.replaceRecipeManagerEntries(helper.getLevel()); | ||
|
||
BlockEntity holder = helper.getBlockEntity(new BlockPos(0, 2, 0)); | ||
if (!(holder instanceof MetaMachineBlockEntity atte)) { | ||
helper.fail("wrong block at relative pos [0,1,0]!"); | ||
return; | ||
} | ||
MetaMachine machine = atte.getMetaMachine(); | ||
if (!(machine instanceof IRecipeLogicMachine rlm)) { | ||
helper.fail("wrong machine in MetaMachineBlockEntity!"); | ||
return; | ||
} | ||
|
||
GTRecipe recipe = GTRecipeBuilder.ofRaw() | ||
.id(GTCEu.id("test")) | ||
.inputItems(new ItemStack(Blocks.COBBLESTONE)) | ||
.outputItems(new ItemStack(Blocks.STONE)) | ||
.EUt(1).duration(1) | ||
.buildRawRecipe(); | ||
// force insert the recipe into the manager. | ||
|
||
if (!hasInjectedRecipe) { | ||
((RecipeManagerAccessor) helper.getLevel().getRecipeManager()).getRawRecipes().get(GTRecipeTypes.CHEMICAL_RECIPES).put(GTCEu.id("test"), recipe); | ||
hasInjectedRecipe = true; | ||
} | ||
|
||
RecipeLogic arl = rlm.getRecipeLogic(); | ||
|
||
arl.findAndHandleRecipe(); | ||
|
||
// no recipe found | ||
helper.assertFalse(arl.isActive(), "Recipe logic is active, even when it shouldn't be"); | ||
helper.assertTrue(arl.getLastRecipe() == null, "Recipe logic has somehow found a recipe, when there should be none"); | ||
|
||
// put an item in the inventory that will trigger recipe recheck | ||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP).get(0)).insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); | ||
// Inputs change. did we detect it ? | ||
// helper.assertTrue(arl.isRecipeDirty(), "Recipe is not dirty"); | ||
arl.findAndHandleRecipe(); | ||
helper.assertFalse(arl.getLastRecipe() == null, "Last recipe is empty, even though recipe logic should've found a recipe."); | ||
helper.assertTrue(arl.isActive(), "Recipelogic is inactive, when it should be active."); | ||
int stackCount = ((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP).get(0)).getStackInSlot(0).getCount(); | ||
helper.assertTrue(stackCount == 15, "Count is wrong (should be 15, when it's %s".formatted(stackCount)); | ||
|
||
// Save a reference to the old recipe so we can make sure it's getting reused | ||
GTRecipe prev = arl.getLastRecipe(); | ||
|
||
// Finish the recipe, the output should generate, and the next iteration should begin | ||
arl.serverTick(); | ||
helper.assertTrue(arl.getLastRecipe() == prev, "lastRecipe is wrong"); | ||
helper.assertTrue(ItemStack.isSameItem(((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP).get(0)).getStackInSlot(0), | ||
new ItemStack(Blocks.STONE, 1)), "wrong output stack."); | ||
helper.assertTrue(arl.isActive(), "RecipeLogic is not active, when it should be."); | ||
|
||
// Complete the second iteration, but the machine stops because its output is now full | ||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP).get(0)).setStackInSlot(0, new ItemStack(Blocks.STONE, 63)); | ||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP).get(0)).setStackInSlot(1, new ItemStack(Blocks.STONE, 64)); | ||
arl.serverTick(); | ||
helper.assertFalse(arl.isActive(), "RecipeLogic is active, when it shouldn't be."); | ||
|
||
// Try to process again and get failed out because of full buffer. | ||
arl.serverTick(); | ||
helper.assertFalse(arl.isActive(), "Recipelogic is active, when it shouldn't be."); | ||
|
||
// Some room is freed in the output bus, so we can continue now. | ||
((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP).get(0)).setStackInSlot(1, ItemStack.EMPTY); | ||
arl.serverTick(); | ||
// helper.assertTrue(arl.isActive(), "Recipelogic is inactive."); | ||
helper.assertTrue(ItemStack.isSameItem(((IItemTransfer)rlm.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP).get(0)).getStackInSlot(0), new ItemStack(Blocks.STONE, 1)), "Wrong stack."); | ||
|
||
// Finish. | ||
helper.succeed(); | ||
} | ||
} |
Oops, something went wrong.