Skip to content

Commit

Permalink
Use a TransformingClassLoader in tests and write Data-Driven Enum Ext…
Browse files Browse the repository at this point in the history
…ension tests (#163)
  • Loading branch information
shartte authored Jun 14, 2024
1 parent 5d17885 commit 70ec5b1
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 277 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mergetool_version=2.0.0
accesstransformers_version=10.0.1
coremods_version=7.0.3
eventbus_version=7.0.16
modlauncher_version=10.1.10
modlauncher_version=11.0.3
securejarhandler_version=3.0.7
bootstraplauncher_version=1.1.8
asm_version=9.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static List<EnumPrototype> load(IModInfo mod, Path path) {
}
return prototypes;
} catch (Throwable e) {
ModLoader.addLoadingIssue(ModLoadingIssue.error("fml.modloading.enumextender.loading_error")
ModLoader.addLoadingIssue(ModLoadingIssue.error("fml.modloading.enumextender.loading_error", path)
.withAffectedMod(mod)
.withCause(e));
return List.of();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@ public Object getParameter(int idx) {
public T getValue() {
if (enumValue == null) {
try {
var loader = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass().getClassLoader();
Class.forName(enumClass.getName(), true, loader);
Class.forName(enumClass.getName(), true, enumClass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return Objects.requireNonNull(enumValue, "Enum not initialized");
return Objects.requireNonNull(enumValue, "Enum not initialized. Did you forget to configure the field holding this proxy as a parameter in the enum extension config file?");
}

@ApiStatus.Internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public static void loadEnumPrototypes(Map<IModInfo, Path> paths) {
.reduce(
new HashMap<>(),
(map, proto) -> {
map.computeIfAbsent(proto.enumName(), $ -> new ArrayList<>()).add(proto);
map.computeIfAbsent(proto.enumName(), ignored -> new ArrayList<>()).add(proto);
return map;
},
(protoOne, protoTwo) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ static void onInitialLoad(IEnvironment environment) throws IncompatibleEnvironme
final String version = LauncherVersion.getVersion();
LOGGER.debug(LogMarkers.CORE, "FML {} loading", version);
final Package modLauncherPackage = ITransformationService.class.getPackage();
LOGGER.debug(LogMarkers.CORE, "FML found ModLauncher version : {}", modLauncherPackage.getImplementationVersion());
if (!modLauncherPackage.isCompatibleWith("4.0")) {
LOGGER.error(LogMarkers.CORE, "Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
throw new IncompatibleEnvironmentException("Incompatible modlauncher found " + modLauncherPackage.getSpecificationVersion());
}
LOGGER.debug(LogMarkers.CORE, "FML found ModLauncher version : {}", environment.getProperty(IEnvironment.Keys.MLIMPL_VERSION.get()).orElse("unknown"));

accessTransformer = ((AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(() -> {
LOGGER.error(LogMarkers.CORE, "Access Transformer library is missing, we need this to run");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public void addEnumExtenders() {
modFiles.stream()
.map(ModFileInfo::getMods)
.flatMap(List::stream)
.forEach(mod -> mod.getConfig().<String>getConfigElement("enumExtender").ifPresent(file -> {
.forEach(mod -> mod.getConfig().<String>getConfigElement("enumExtensions").ifPresent(file -> {
Path path = mod.getOwningFile().getFile().findResource(file);
if (Files.notExists(path)) {
if (!Files.isRegularFile(path)) {
ModLoader.addLoadingIssue(ModLoadingIssue.error("fml.modloading.enumextender.file_not_found", path).withAffectedMod(mod));
return;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,13 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.function.Consumer;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.loading.ModFileBuilder;
import net.neoforged.fml.loading.LauncherTest;
import org.intellij.lang.annotations.Language;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

class RuntimeDistCleanerTest {
@TempDir
Path tempDir;

class RuntimeDistCleanerTest extends LauncherTest {
@Test
void testStripInterface() throws Exception {
transformTestClass(Dist.CLIENT, """
Expand Down Expand Up @@ -123,26 +116,20 @@ private void transformTestClass(Dist dist, @Language("java") String classContent
}

private void transformTestClass(Dist dist, @Language("java") String classContent, Consumer<Class<?>> asserter) throws Exception {
var distCleaner = new RuntimeDistCleaner();
distCleaner.setDistribution(dist);
if (dist.isClient()) {
installation.setupProductionClient();
} else {
installation.setupProductionServer();
}

var modJar = tempDir.resolve("modjar.jar");
new ModFileBuilder(modJar)
installation.buildModJar("modjar.jar")
.withTestmodModsToml()
.addClass("test.Test", classContent)
.withTransform((type, classNode) -> {
var phases = distCleaner.handlesClass(type, false);
for (var phase : phases) {
distCleaner.processClassWithFlags(phase, classNode, type, "");
}
return classNode;
})
.build();

try (var cl = new URLClassLoader(new URL[] {
modJar.toUri().toURL()
})) {
var testClass = cl.loadClass("test.Test");
asserter.accept(testClass);
}
launchAndLoad(dist.isClient() ? "forgeclient" : "forgeserver");

var testClass = Class.forName("test.Test", true, gameClassLoader);
asserter.accept(testClass);
}
}
Loading

0 comments on commit 70ec5b1

Please sign in to comment.