aboutsummaryrefslogtreecommitdiff
path: root/src/functionalTest/java/kubatech/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/functionalTest/java/kubatech/test')
-rw-r--r--src/functionalTest/java/kubatech/test/EIGTests.java277
-rw-r--r--src/functionalTest/java/kubatech/test/kubatechTestMod.java101
2 files changed, 378 insertions, 0 deletions
diff --git a/src/functionalTest/java/kubatech/test/EIGTests.java b/src/functionalTest/java/kubatech/test/EIGTests.java
new file mode 100644
index 0000000000..7cdfa8dae4
--- /dev/null
+++ b/src/functionalTest/java/kubatech/test/EIGTests.java
@@ -0,0 +1,277 @@
+/*
+ * spotless:off
+ * KubaTech - Gregtech Addon
+ * Copyright (C) 2022 - 2024 kuba6000
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <https://www.gnu.org/licenses/>.
+ * spotless:on
+ */
+
+package kubatech.test;
+
+import static gregtech.api.util.GT_RecipeBuilder.HOURS;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.util.Map;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.MinecraftException;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldProvider;
+import net.minecraft.world.WorldProviderSurface;
+import net.minecraft.world.WorldServer;
+import net.minecraft.world.WorldSettings;
+import net.minecraft.world.WorldType;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraft.world.chunk.storage.IChunkLoader;
+import net.minecraft.world.storage.IPlayerFileData;
+import net.minecraft.world.storage.ISaveHandler;
+import net.minecraft.world.storage.WorldInfo;
+import net.minecraftforge.common.DimensionManager;
+
+import org.junit.jupiter.api.Test;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.common.blocks.GT_Item_Machines;
+import ic2.api.crops.CropCard;
+import ic2.api.crops.Crops;
+import ic2.core.Ic2Items;
+import ic2.core.crop.TileEntityCrop;
+import ic2.core.item.ItemCropSeed;
+import kubatech.api.eig.EIGDropTable;
+import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse;
+import kubatech.tileentity.gregtech.multiblock.eigbuckets.EIGIC2Bucket;
+
+public class EIGTests {
+
+ private static final int EIG_CONTROLLER_METADATA = 12_792;
+ private static final int EIG_SIMULATION_TIME = 24 * HOURS;
+ private static final int NUMBER_OF_TESTS_TO_DO = 1000;
+
+ static World myWorld;
+
+ public EIGTests() {
+ if (!DimensionManager.isDimensionRegistered(256)) {
+ DimensionManager.registerProviderType(256, WorldProviderSurface.class, false);
+ DimensionManager.registerDimension(256, 256);
+ }
+ if (myWorld == null) {
+ myWorld = new WorldServer(MinecraftServer.getServer(), new ISaveHandler() {
+
+ @Override
+ public WorldInfo loadWorldInfo() {
+ return null;
+ }
+
+ @Override
+ public void checkSessionLock() throws MinecraftException {
+
+ }
+
+ @Override
+ public IChunkLoader getChunkLoader(WorldProvider p_75763_1_) {
+ return null;
+ }
+
+ @Override
+ public void saveWorldInfoWithPlayer(WorldInfo p_75755_1_, NBTTagCompound p_75755_2_) {
+
+ }
+
+ @Override
+ public void saveWorldInfo(WorldInfo p_75761_1_) {
+
+ }
+
+ @Override
+ public IPlayerFileData getSaveHandler() {
+ return null;
+ }
+
+ @Override
+ public void flush() {
+
+ }
+
+ @Override
+ public File getWorldDirectory() {
+ return null;
+ }
+
+ @Override
+ public File getMapFileFromName(String p_75758_1_) {
+ return null;
+ }
+
+ @Override
+ public String getWorldDirectoryName() {
+ return "dummy";
+ }
+ },
+ "DummyTestWorld",
+ 256,
+ new WorldSettings(256, WorldSettings.GameType.SURVIVAL, false, false, WorldType.DEFAULT),
+ MinecraftServer.getServer().theProfiler) {
+
+ @Override
+ public File getChunkSaveLocation() {
+ return new File("ignoreme");
+ }
+
+ @Override
+ public int getBlockLightValue(int p_72957_1_, int p_72957_2_, int p_72957_3_) {
+ return 4;
+ }
+
+ @Override
+ public BiomeGenBase getBiomeGenForCoords(int x, int z) {
+ // give the environment a fighting chance of being bearable for crops
+ return BiomeGenBase.jungle;
+ }
+ };
+ }
+ }
+
+ EIGDropTable getRealDrops(TileEntityCrop cropTile, CropCard cc, int growth, int gain, int resistance) {
+ cropTile.setCrop(cc);
+ cropTile.setGrowth((byte) growth);
+ cropTile.setGain((byte) gain);
+ cropTile.setResistance((byte) resistance);
+ EIGDropTable expected = new EIGDropTable();
+ byte startingHumidity = cropTile.humidity;
+ byte startingNutrients = cropTile.nutrients;
+ byte startingAirQuality = cropTile.airQuality;
+ int startingNutrientStorage = cropTile.nutrientStorage;
+ int startingWaterStorage = cropTile.waterStorage;
+ // reset the crop to it's stage after harvest
+ cropTile.setSize((byte) cc.maxSize());
+ cropTile.setSize(cc.getSizeAfterHarvest(cropTile));
+ for (int timeElapsed = 0; timeElapsed < EIG_SIMULATION_TIME; timeElapsed += TileEntityCrop.tickRate) {
+ // force reset the stats to max because the eig shouldn't make them change.
+ // some crops check water storage in the can grow and we are ticking which consumes water.
+ cropTile.humidity = startingHumidity;
+ cropTile.nutrients = startingNutrients;
+ cropTile.airQuality = startingAirQuality;
+ cropTile.nutrientStorage = startingNutrientStorage;
+ cropTile.waterStorage = startingWaterStorage;
+ // if fully grown harvest the crop
+ if (cropTile.getSize() >= cc.maxSize()) {
+ ItemStack[] stacks = cropTile.harvest_automated(false);
+ for (ItemStack stack : stacks) {
+ expected.addDrop(stack, stack.stackSize);
+ }
+ }
+ cropTile.tick();
+ }
+ // ensure it leaves the same way it came in
+ cropTile.humidity = startingHumidity;
+ cropTile.nutrients = startingNutrients;
+ cropTile.airQuality = startingAirQuality;
+ cropTile.nutrientStorage = startingNutrientStorage;
+ cropTile.waterStorage = startingWaterStorage;
+ return expected;
+ }
+
+ EIGDropTable getEIGDrops(GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG, ItemStack stack) {
+ EIGDropTable generated = new EIGDropTable();
+ EIGIC2Bucket bucket = new EIGIC2Bucket(stack, stack.stackSize, null, false);
+ bucket.revalidate(EIG);
+ bucket.addProgress(EIG_SIMULATION_TIME, generated);
+ return generated;
+ }
+
+ @Test
+ void EIGDrops() {
+ myWorld.setBlock(10, 80, 0, Blocks.farmland, 0, 0);
+ myWorld.setBlock(10, 81, 0, Block.getBlockFromItem(Ic2Items.crop.getItem()), 0, 0);
+ // using stickreed since it has a random stage after harvest.
+ // it's also more preferable to test using faster growing crops since they can be harvested more often.
+ CropCard cc = Crops.instance.getCropCard("IC2", "stickreed");
+ TileEntityCrop cropTile = (TileEntityCrop) myWorld.getTileEntity(10, 81, 0);
+ ItemStack ccStack = ItemCropSeed.generateItemStackFromValues(cc, (byte) 10, (byte) 10, (byte) 10, (byte) 1);
+
+ GT_Item_Machines itemMachines = (GT_Item_Machines) Item.getItemFromBlock(GregTech_API.sBlockMachines);
+ itemMachines.placeBlockAt(
+ new ItemStack(itemMachines, 1, EIG_CONTROLLER_METADATA),
+ null,
+ myWorld,
+ 0,
+ 81,
+ 0,
+ 2,
+ 0,
+ 0,
+ 0,
+ EIG_CONTROLLER_METADATA);
+ IGregTechTileEntity te = (IGregTechTileEntity) myWorld.getTileEntity(0, 81, 0);
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG = (GT_MetaTileEntity_ExtremeIndustrialGreenhouse) te
+ .getMetaTileEntity();
+
+ // update stats of crop TE to those provided by the EIG
+ cropTile.humidity = EIGIC2Bucket.getHumidity(EIG, false);
+ cropTile.nutrients = EIGIC2Bucket.getNutrients(EIG);
+ cropTile.airQuality = EIGIC2Bucket.getAirQuality(EIG);
+
+ int[] abc = new int[] { 0, -2, 3 };
+ int[] xyz = new int[] { 0, 0, 0 };
+ EIG.getExtendedFacing()
+ .getWorldOffset(abc, xyz);
+ xyz[0] += te.getXCoord();
+ xyz[1] += te.getYCoord();
+ xyz[2] += te.getZCoord();
+
+ myWorld.setBlock(xyz[0], xyz[1] - 2, xyz[2], GregTech_API.sBlockCasings4, 1, 0);
+ myWorld.setBlock(xyz[0], xyz[1] - 1, xyz[2], Blocks.farmland, 0, 0);
+
+ ItemStack stackToTest = null;
+
+ double realAvg = 0, eigAvg = 0;
+
+ for (int i = 0; i < NUMBER_OF_TESTS_TO_DO; i++) {
+ EIGDropTable expected = getRealDrops(cropTile, cc, 10, 10, 10);
+ EIGDropTable generated = getEIGDrops(EIG, ccStack);
+
+ // we are only comparing one item from drops
+ if (stackToTest == null) {
+ stackToTest = expected.entrySet()
+ .stream()
+ .max(Map.Entry.comparingByValue())
+ .get()
+ .getKey();
+ }
+
+ realAvg += expected.getItemAmount(stackToTest);
+ // EIG with ic2 crops doesn't actually have variance, it uses very precise approximations that create
+ // accurate growth rate and drop quality approximations.
+ eigAvg += generated.getItemAmount(stackToTest);
+ }
+ realAvg /= NUMBER_OF_TESTS_TO_DO;
+ eigAvg /= NUMBER_OF_TESTS_TO_DO;
+ double accuracy = Math.min(realAvg / eigAvg, eigAvg / realAvg);
+
+ String debugInfo = String.format("realAvg: %.5f | eigAvg : %.5f | accuracy = %.5f", realAvg, eigAvg, accuracy);
+ System.out.println(debugInfo);
+
+ // We aim for about 99% accuracy over here.
+ assertTrue(accuracy >= 0.99d);
+ }
+
+}
diff --git a/src/functionalTest/java/kubatech/test/kubatechTestMod.java b/src/functionalTest/java/kubatech/test/kubatechTestMod.java
new file mode 100644
index 0000000000..bc68d3f203
--- /dev/null
+++ b/src/functionalTest/java/kubatech/test/kubatechTestMod.java
@@ -0,0 +1,101 @@
+package kubatech.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.Mod.EventHandler;
+import cpw.mods.fml.common.event.FMLPreInitializationEvent;
+import cpw.mods.fml.common.event.FMLServerStartedEvent;
+import gregtech.GT_Mod;
+
+@Mod(
+ modid = "kubatech-tests",
+ name = "KubaTech Dev Tests",
+ version = "1.0",
+ dependencies = "required-after:kubatech;required-after:gregtech;after:berriespp;")
+public class kubatechTestMod {
+
+ @EventHandler
+ public void preInit(FMLPreInitializationEvent ev) {
+ // Disable GT5u messing with vanilla recipes for unit tests
+ GT_Mod.gregtechproxy.mNerfedWoodPlank = false;
+ GT_Mod.gregtechproxy.mNerfedVanillaTools = false;
+ }
+
+ @EventHandler
+ public void onServerStarted(FMLServerStartedEvent startedEv) {
+ MinecraftServer.getServer()
+ .addChatMessage(new ChatComponentText("Running KT unit tests..."));
+ runTests();
+ MinecraftServer.getServer()
+ .addChatMessage(new ChatComponentText("Running KT unit tests finished"));
+ }
+
+ public 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("kubatech.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");
+ }
+ }
+
+}