Skip to content

Commit

Permalink
Port fabric-gametest-api-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed Jun 15, 2024
1 parent 8736915 commit 29f188c
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 364 deletions.
2 changes: 1 addition & 1 deletion fabric-gametest-api-v1/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ loom {
vmArg "-Dfabric-api.gametest.structures.output-dir=${file("src/testmod/resources/data/fabric-gametest-api-v1-testmod/gametest/structure")}"

ideConfigGenerated = false
source sourceSets.testmodClient
// source sourceSets.testmodClient
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,18 @@

package net.fabricmc.fabric.impl.gametest;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.function.Consumer;

import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.minecraft.core.BlockPos;
import cpw.mods.modlauncher.api.LambdaExceptionUtils;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.gametest.framework.GameTestRegistry;
import net.minecraft.gametest.framework.GameTestServer;
import net.minecraft.gametest.framework.GlobalTestReporter;
import net.minecraft.gametest.framework.TestCommand;
import net.minecraft.gametest.framework.TestFunction;
import net.minecraft.resources.FileToIdConverter;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.fabricmc.api.EnvType;
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
import net.fabricmc.loader.api.FabricLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class FabricGameTestHelper {
public static final boolean ENABLED = System.getProperty("fabric-api.gametest") != null;
import java.lang.reflect.Method;

public final class FabricGameTestHelper {
/**
* When enabled the {@link TestCommand} and related arguments will be registered.
*
Expand All @@ -63,68 +46,7 @@ public final class FabricGameTestHelper {
private FabricGameTestHelper() {
}

public static void runHeadlessServer(LevelStorageSource.LevelStorageAccess session, PackRepository resourcePackManager) {
String reportPath = System.getProperty("fabric-api.gametest.report-file");

if (reportPath != null) {
try {
GlobalTestReporter.replaceWith(new SavingXmlReportingTestCompletionListener(new File(reportPath)));
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
}

LOGGER.info("Starting test server");
MinecraftServer server = GameTestServer.spin(thread -> {
return GameTestServer.create(thread, session, resourcePackManager, getTestFunctions(), BlockPos.ZERO);
});
}

public static Consumer<GameTestHelper> getTestMethodInvoker(Method method) {
return testContext -> {
Class<?> testClass = method.getDeclaringClass();

Constructor<?> constructor;

try {
constructor = testClass.getConstructor();
} catch (NoSuchMethodException e) {
throw new RuntimeException("Test class (%s) provided by (%s) must have a public default or no args constructor".formatted(testClass.getSimpleName(), FabricGameTestModInitializer.getModIdForTestClass(testClass)));
}

Object testObject;

try {
testObject = constructor.newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Failed to create instance of test class (%s)".formatted(testClass.getCanonicalName()), e);
}

if (testObject instanceof FabricGameTest fabricGameTest) {
fabricGameTest.invokeTestMethod(testContext, method);
} else {
invokeTestMethod(testContext, method, testObject);
}
};
}

public static void invokeTestMethod(GameTestHelper testContext, Method method, Object testObject) {
try {
method.invoke(testObject, testContext);
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to invoke test method (%s) in (%s) because %s".formatted(method.getName(), method.getDeclaringClass().getCanonicalName(), e.getMessage()), e);
} catch (InvocationTargetException e) {
LOGGER.error("Exception occurred when invoking test method {} in ({})", method.getName(), method.getDeclaringClass().getCanonicalName(), e);

if (e.getCause() instanceof RuntimeException runtimeException) {
throw runtimeException;
} else {
throw new RuntimeException(e.getCause());
}
}
}

private static Collection<TestFunction> getTestFunctions() {
return GameTestRegistry.getAllTestFunctions();
LambdaExceptionUtils.uncheck(() -> method.invoke(testObject, testContext));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,4 @@ public void onInitialize() {
LOGGER.debug("Registered test class {} for mod {}", testClass.getCanonicalName(), modid);
}
}

public static String getModIdForTestClass(Class<?> testClass) {
if (!GAME_TEST_IDS.containsKey(testClass)) {
throw new UnsupportedOperationException("The test class (%s) was not registered using the '%s' entrypoint".formatted(testClass.getCanonicalName(), ENTRYPOINT_KEY));
}

return GAME_TEST_IDS.get(testClass);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.fabricmc.fabric.mixin.gametest;

import net.neoforged.neoforge.gametest.GameTestHooks;
import org.sinytra.fabric.gametest_api_v1.FabricGameTestApiV1;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.lang.reflect.Method;

@Mixin(value = GameTestHooks.class, remap = false)
public class GameTestHooksMixin {

@Inject(method = "getTemplateNamespace", at = @At("TAIL"), cancellable = true)
private static void provideFabricTestNamespace(Method method, CallbackInfoReturnable<String> cir) {
String namespace = FabricGameTestApiV1.getGameTestNamespace(method);
if (namespace != null) {
cir.setReturnValue(namespace);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.fabricmc.fabric.mixin.gametest;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.gametest.framework.GameTestRegistry;
import org.sinytra.fabric.gametest_api_v1.FabricGameTestApiV1;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

import java.lang.reflect.Method;

@Mixin(value = GameTestRegistry.class)
public class GameTestRegistryMixin {

@ModifyVariable(method = "turnMethodIntoTestFunction", at = @At(value = "INVOKE", target = "Lnet/minecraft/gametest/framework/GameTest;batch()Ljava/lang/String;"), ordinal = 3)
private static String provideFabricTestName(String str, Method method) {
if (FabricGameTestApiV1.shouldProcess(method)) {
GameTest gametest = method.getAnnotation(GameTest.class);
if (gametest.templateNamespace().isEmpty() && !gametest.template().isEmpty()) {
return gametest.template();
}
}
return str;
}

@WrapOperation(method = "lambda$turnMethodIntoConsumer$5(Ljava/lang/reflect/Method;Ljava/lang/Object;)V", at = @At(value = "INVOKE", target = "Ljava/lang/reflect/Method;invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"))
private static Object redirectTestInvoker(Method method, Object instance, Object[] args, Operation<Object> original) {
if (instance instanceof FabricGameTest fabricGameTest && args.length > 0 && args[0] instanceof GameTestHelper ctx) {
fabricGameTest.invokeTestMethod(ctx, method);
return null;
}
return original.call(method, instance, args);
}
}

This file was deleted.

Loading

0 comments on commit 29f188c

Please sign in to comment.