-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add testcase for RuntimeDistCleaner (#156)
- Loading branch information
Showing
2 changed files
with
219 additions
and
4 deletions.
There are no files selected for viewing
148 changes: 148 additions & 0 deletions
148
loader/src/test/java/net/neoforged/fml/common/asm/RuntimeDistCleanerTest.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,148 @@ | ||
/* | ||
* Copyright (c) NeoForged and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.fml.common.asm; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
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 org.intellij.lang.annotations.Language; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
|
||
class RuntimeDistCleanerTest { | ||
@TempDir | ||
Path tempDir; | ||
|
||
@Test | ||
void testStripInterface() throws Exception { | ||
transformTestClass(Dist.CLIENT, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT, _interface = java.lang.AutoCloseable.class) | ||
public class Test implements AutoCloseable { | ||
public void close() {} | ||
} | ||
""", clazz -> assertThat(clazz.getInterfaces()).contains(AutoCloseable.class)); | ||
} | ||
|
||
@Test | ||
void testKeepInterface() throws Exception { | ||
transformTestClass(Dist.DEDICATED_SERVER, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT, _interface = java.lang.AutoCloseable.class) | ||
public class Test implements AutoCloseable { | ||
public void close() {} | ||
} | ||
""", clazz -> assertThat(clazz.getInterfaces()).doesNotContain(AutoCloseable.class)); | ||
} | ||
|
||
@Test | ||
void testRejectLoadingClientClassOnDedicatedServer() throws Exception { | ||
assertThatThrownBy(() -> transformTestClass(Dist.DEDICATED_SERVER, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT) | ||
public class Test { | ||
} | ||
""")).hasMessageContaining("Attempted to load class test/Test for invalid dist DEDICATED_SERVER"); | ||
} | ||
|
||
@Test | ||
void testRejectLoadingDedicatedServerClassOnClient() throws Exception { | ||
assertThatThrownBy(() -> transformTestClass(Dist.CLIENT, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.DEDICATED_SERVER) | ||
public class Test { | ||
} | ||
""")).hasMessageContaining("Attempted to load class test/Test for invalid dist CLIENT"); | ||
} | ||
|
||
@Test | ||
void testAllowLoadingClientClassOnClient() throws Exception { | ||
transformTestClass(Dist.CLIENT, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT) | ||
public class Test { | ||
} | ||
"""); | ||
} | ||
|
||
@Test | ||
void testAllowLoadingDedicatedServerClassOnDedicatedServer() throws Exception { | ||
transformTestClass(Dist.DEDICATED_SERVER, """ | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.DEDICATED_SERVER) | ||
public class Test { | ||
} | ||
"""); | ||
} | ||
|
||
@Test | ||
void testRemoveField() throws Exception { | ||
transformTestClass(Dist.DEDICATED_SERVER, """ | ||
public class Test { | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT) | ||
public int field; | ||
} | ||
""", clazz -> assertThat(clazz.getFields()).extracting(Field::getName).doesNotContain("field")); | ||
} | ||
|
||
@Test | ||
void testRemoveMethod() throws Exception { | ||
transformTestClass(Dist.DEDICATED_SERVER, """ | ||
public class Test { | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT) | ||
public void method() {} | ||
} | ||
""", clazz -> assertThat(clazz.getDeclaredMethods()) | ||
// Coverage on Gradle with jacoco inserts methods | ||
.filteredOn(m -> !m.getName().contains("jacoco")) | ||
.isEmpty()); | ||
} | ||
|
||
@Test | ||
void testRemoveLambdasInsideOfMethod() throws Exception { | ||
transformTestClass(Dist.DEDICATED_SERVER, """ | ||
import java.util.function.IntSupplier; | ||
public class Test { | ||
@net.neoforged.api.distmarker.OnlyIn(value = net.neoforged.api.distmarker.Dist.CLIENT) | ||
public IntSupplier method(int arg) { | ||
return () -> arg + 1; | ||
} | ||
} | ||
""", clazz -> assertThat(clazz.getDeclaredMethods()) | ||
// Coverage on Gradle with jacoco inserts methods | ||
.filteredOn(m -> !m.getName().contains("jacoco")) | ||
.isEmpty()); | ||
} | ||
|
||
private void transformTestClass(Dist dist, @Language("java") String classContent) throws Exception { | ||
transformTestClass(dist, classContent, ignored -> {}); | ||
} | ||
|
||
private void transformTestClass(Dist dist, @Language("java") String classContent, Consumer<Class<?>> asserter) throws Exception { | ||
var distCleaner = new RuntimeDistCleaner(); | ||
distCleaner.getExtension().accept(dist); | ||
|
||
var modJar = tempDir.resolve("modjar.jar"); | ||
new ModFileBuilder(modJar) | ||
.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); | ||
} | ||
} | ||
} |
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