Skip to content

Commit

Permalink
Add unit test for recipe search (#2394)
Browse files Browse the repository at this point in the history
  • Loading branch information
miozune authored Dec 6, 2023
1 parent 93a498b commit b527397
Show file tree
Hide file tree
Showing 6 changed files with 332 additions and 0 deletions.
40 changes: 40 additions & 0 deletions addon.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,43 @@ minecraft {
injectedTags.put 'VERSION_PATCH', vPatch
project.logger.log(logLevel, 'Using ({}, {}, {}) as NBT version', vMajor, vMinor, vPatch)
}

SourceSet functionalTestSet = null

sourceSets {
functionalTestSet = create("functionalTest") {
java {
srcDir("src/functionalTest/java")
compileClasspath += sourceSets.patchedMc.output + sourceSets.main.output
}
}
}

configurations { configs ->
// Keep all dependencies from the main mod in the functional test mod
named(functionalTestSet.compileClasspathConfigurationName).configure {it.extendsFrom(named("compileClasspath").get())}
named(functionalTestSet.runtimeClasspathConfigurationName).configure {it.extendsFrom(named("runtimeClasspath").get())}
named(functionalTestSet.annotationProcessorConfigurationName).configure {it.extendsFrom(named("annotationProcessor").get())}
}

tasks.register(functionalTestSet.jarTaskName, Jar) {
from(functionalTestSet.output)
archiveClassifier.set("functionalTests")
// we don't care about the version number here, keep it stable to avoid polluting the tmp directory
archiveVersion.set("1.0")
destinationDirectory.set(new File(buildDir, "tmp"))
}
tasks.named("assemble").configure {
dependsOn(functionalTestSet.jarTaskName)
}

// Run tests in the default runServer/runClient configurations
tasks.named("runServer", JavaExec).configure {
dependsOn(functionalTestSet.jarTaskName)
classpath(configurations.named(functionalTestSet.runtimeClasspathConfigurationName), tasks.named(functionalTestSet.jarTaskName))
}

tasks.named("runClient", JavaExec).configure {
dependsOn(functionalTestSet.jarTaskName)
classpath(configurations.named(functionalTestSet.runtimeClasspathConfigurationName), tasks.named(functionalTestSet.jarTaskName))
}
6 changes: 6 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,10 @@ dependencies {
testImplementation(platform('org.junit:junit-bom:5.9.2'))
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation("org.mockito:mockito-core:3.+")

functionalTestImplementation(platform('org.junit:junit-bom:5.9.2'))
functionalTestImplementation('org.junit.jupiter:junit-jupiter')
functionalTestImplementation('org.junit.platform:junit-platform-engine')
functionalTestImplementation('org.junit.platform:junit-platform-launcher')
functionalTestImplementation('org.junit.platform:junit-platform-reporting')
}
86 changes: 86 additions & 0 deletions src/functionalTest/java/gregtech/test/GT5TestMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package gregtech.test;

import java.io.File;
import java.io.PrintWriter;
import java.nio.file.FileSystems;
import java.nio.file.Path;

import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatComponentText;

import org.apache.commons.io.output.CloseShieldOutputStream;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.LauncherSession;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
import org.junit.platform.reporting.legacy.xml.LegacyXmlReportGeneratingListener;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLServerStartedEvent;

@Mod(modid = "gt5-tests", name = "GT5 Dev Tests", version = "1.0", dependencies = "required-after:gregtech")
public class GT5TestMod {

@Mod.EventHandler
public void onServerStarted(FMLServerStartedEvent event) {
MinecraftServer.getServer()
.addChatMessage(new ChatComponentText("Running GT5 unit tests..."));
runTests();
MinecraftServer.getServer()
.addChatMessage(new ChatComponentText("Running GT5 unit tests finished"));
}

private void runTests() {
// https://junit.org/junit5/docs/current/user-guide/#launcher-api
System.setProperty("junit.platform.reporting.open.xml.enabled", "false");
final Path testsXmlOutDir = FileSystems.getDefault()
.getPath("./junit-out/")
.toAbsolutePath();
final File testsXmlOutDirFile = testsXmlOutDir.toFile();
testsXmlOutDirFile.mkdirs();
{
File[] fileList = testsXmlOutDirFile.listFiles();
if (fileList != null) {
for (File child : fileList) {
if (child.isFile() && child.getName()
.endsWith(".xml")) {
child.delete();
}
}
}
}
final LauncherDiscoveryRequest discovery = LauncherDiscoveryRequestBuilder.request()
.selectors(DiscoverySelectors.selectPackage("gregtech.test"))
.build();
final SummaryGeneratingListener summaryGenerator = new SummaryGeneratingListener();
final TestExecutionSummary summary;
try (PrintWriter stderrWriter = new PrintWriter(new CloseShieldOutputStream(System.err), true)) {
final LegacyXmlReportGeneratingListener xmlGenerator = new LegacyXmlReportGeneratingListener(
testsXmlOutDir,
stderrWriter);
try (LauncherSession session = LauncherFactory.openSession()) {
final Launcher launcher = session.getLauncher();
final TestPlan plan = launcher.discover(discovery);
launcher.registerTestExecutionListeners(summaryGenerator, xmlGenerator);
launcher.execute(plan);
}
summary = summaryGenerator.getSummary();

summary.printFailuresTo(stderrWriter, 32);
summary.printTo(stderrWriter);
stderrWriter.flush();
}
// Throw an exception if running via `runServer`
if (summary.getTotalFailureCount() > 0 && FMLCommonHandler.instance()
.getSide()
.isServer()) {
throw new RuntimeException("Some of the unit tests failed to execute, check the log for details");
}
}
}
185 changes: 185 additions & 0 deletions src/functionalTest/java/gregtech/test/GTRecipeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package gregtech.test;

import static gregtech.api.enums.GT_Values.RA;
import static gregtech.api.enums.ItemList.Circuit_Advanced;
import static gregtech.api.enums.ItemList.Circuit_Nanoprocessor;
import static gregtech.api.enums.ItemList.Circuit_Parts_Crystal_Chip_Master;
import static gregtech.api.enums.ItemList.IC2_LapotronCrystal;
import static gregtech.api.enums.Materials.Advanced;
import static gregtech.api.enums.Materials.BlueTopaz;
import static gregtech.api.enums.Mods.GregTech;
import static gregtech.api.enums.OrePrefixes.circuit;
import static gregtech.api.enums.OrePrefixes.lens;
import static gregtech.api.util.GT_ModHandler.getModItem;
import static gregtech.api.util.GT_OreDictUnificator.get;
import static gregtech.api.util.GT_OreDictUnificator.isItemStackInstanceOf;
import static gregtech.api.util.GT_Utility.copyAmount;
import static net.minecraft.init.Blocks.chest;
import static net.minecraft.init.Blocks.iron_ore;
import static net.minecraft.init.Blocks.lapis_block;
import static net.minecraft.init.Blocks.log;
import static net.minecraft.init.Blocks.planks;
import static net.minecraft.init.Items.iron_ingot;
import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

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

import gregtech.api.recipe.RecipeMap;
import gregtech.api.recipe.RecipeMapBuilder;
import gregtech.api.util.GT_Recipe;

class GTRecipeTest {

static RecipeMap<?> recipeMap;
static GT_Recipe lapotronChipRecipe;

@BeforeAll
static void setup() {
recipeMap = RecipeMapBuilder.of("__test__")
.maxIO(9, 1, 1, 0)
.build();

RA.stdBuilder()
.itemInputs(new ItemStack(log, 2, WILDCARD_VALUE), new ItemStack(planks, 2, WILDCARD_VALUE))
.itemOutputs(new ItemStack(chest, 1))
.duration(0)
.eut(0)
.addTo(recipeMap);

RA.stdBuilder()
.itemInputs(new ItemStack(lapis_block, 1), get(circuit, Advanced, 1))
.itemOutputs(IC2_LapotronCrystal.get(1))
.duration(0)
.eut(0)
.addTo(recipeMap);

lapotronChipRecipe = RA.stdBuilder()
.itemInputs(IC2_LapotronCrystal.getWildcard(1), copyAmount(0, get(lens, BlueTopaz, 1)))
.itemOutputs(Circuit_Parts_Crystal_Chip_Master.get(3))
.duration(0)
.eut(0)
.addTo(recipeMap)
.toArray(new GT_Recipe[0])[0];

RA.stdBuilder()
.itemInputs(getModItem(GregTech.ID, "gt.blockores", 1, 32))
.itemOutputs(new ItemStack(iron_ingot, 1))
.duration(0)
.eut(0)
.addTo(recipeMap);
}

@Test
void ensureRecipesAdded() {
assertEquals(
recipeMap.getAllRecipes()
.size(),
4);
}

@Test
void findWithExactSameInputs() {
GT_Recipe recipe = recipeMap.findRecipeQuery()
.items(new ItemStack(lapis_block, 1), get(circuit, Advanced, 1))
.find();
assertNotNull(recipe);
}

@Test
void findWildcardWithExactSameInputs() {
GT_Recipe chestRecipe = recipeMap.findRecipeQuery()
.items(new ItemStack(log, 2, WILDCARD_VALUE), new ItemStack(planks, 2, WILDCARD_VALUE))
.find();
assertNotNull(chestRecipe);

GT_Recipe lapotronChipRecipe = recipeMap.findRecipeQuery()
.items(IC2_LapotronCrystal.getWildcard(1), copyAmount(0, get(lens, BlueTopaz, 1)))
.find();
assertNotNull(lapotronChipRecipe);
}

@Test
void findWildcardWithDifferentMeta() {
// https://github.com/GTNewHorizons/GT5-Unofficial/pull/2364/commits/e7112fce5f24431f3a4ad19288d662b93cbb91f2
GT_Recipe recipe = recipeMap.findRecipeQuery()
.items(new ItemStack(log, 2, 0), new ItemStack(planks, 2, 1))
.find();
assertNotNull(recipe);
}

@Test
void findWithNBT() {
// https://github.com/GTNewHorizons/GT5-Unofficial/pull/2364/commits/844a38662b05494b42a4439bbc0e6d4d7df1a683
ItemStack lapisBlock = new ItemStack(lapis_block, 1);
NBTTagCompound tag = new NBTTagCompound();
tag.setFloat("charge", 123456);
lapisBlock.stackTagCompound = tag;
GT_Recipe recipe = recipeMap.findRecipeQuery()
.items(lapisBlock, get(circuit, Advanced, 1))
.find();
assertNotNull(recipe);
}

@Test
void rejectWithInsufficientAmount() {
GT_Recipe recipe = recipeMap.findRecipeQuery()
.items(new ItemStack(log, 1, 0), new ItemStack(planks, 1, 0))
.find();
assertNull(recipe);
}

@Test
void rejectWithoutNonConsumable() {
// https://github.com/GTNewHorizons/GT5-Unofficial/pull/2364/commits/bfc93bff7ed34616021e8c5b6dbdc50dd7096af5
GT_Recipe recipe = recipeMap.findRecipeQuery()
.items(IC2_LapotronCrystal.get(1))
.cachedRecipe(lapotronChipRecipe)
.find();
assertNull(recipe);
}

@Test
void findOredicted() {
// https://github.com/GTNewHorizons/GT5-Unofficial/pull/2373
assertTrue(
isItemStackInstanceOf(Circuit_Nanoprocessor.get(1), "circuitAdvanced"),
"Nanoprocessor is not registered as HV circuit");
GT_Recipe recipeByNanoProcessor = recipeMap.findRecipeQuery()
.items(new ItemStack(lapis_block, 1), Circuit_Nanoprocessor.get(1))
.find();
assertNotNull(recipeByNanoProcessor);

assertTrue(
isItemStackInstanceOf(Circuit_Advanced.get(1), "circuitAdvanced"),
"Processor Assembly is not registered as HV circuit");
GT_Recipe recipeByCircuitAssembly = recipeMap.findRecipeQuery()
.items(new ItemStack(lapis_block, 1), Circuit_Advanced.get(1))
.find();
assertNotNull(recipeByCircuitAssembly);
}

@Test
void findWithSpecificOreDictionary() {
// https://github.com/GTNewHorizons/GT5-Unofficial/pull/2379
// We cannot use circuit assembling recipe like the issue mentioned above,
// as mUnificationTarget is not set for circuits in GT5.
// But it works in the same way; specific circuit -> GT ore block, unificated circuit -> vanilla ore block
GT_Recipe recipeCorrectOre = recipeMap.findRecipeQuery()
.items(getModItem(GregTech.ID, "gt.blockores", 1, 32))
.find();
assertNotNull(recipeCorrectOre);

GT_Recipe recipeWrongOre = recipeMap.findRecipeQuery()
.items(new ItemStack(iron_ore, 1))
.find();
assertNull(recipeWrongOre);
}
}
15 changes: 15 additions & 0 deletions src/functionalTest/resources/mcmod.info
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"modid":"GT5-tests",
"name":"GT5 Dev Tests",
"description":"GT5 Tests to run in the development environment",
"version":"1.0",
"mcversion":"1.7.10",
"url":"https://github.com/GTNewHorizons/GT5-Unofficial",
"updateUrl":"",
"authorList":[],
"credits":"",
"logoFile":"",
"screenshots":[]
}
]
Empty file.

0 comments on commit b527397

Please sign in to comment.