aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Herzig <jonas@spark-squared.com>2021-11-10 09:34:39 +0100
committerJonas Herzig <jonas@spark-squared.com>2021-11-10 18:11:16 +0100
commit7d62cd890cb44945e772e18cdb457b1173f4f853 (patch)
treee6f0e969442f464556289a090769e966bc0e2efe
parent89e079621c7867036d4ac77b018ad904d21364b5 (diff)
downloadRemap-7d62cd890cb44945e772e18cdb457b1173f4f853.tar.gz
Remap-7d62cd890cb44945e772e18cdb457b1173f4f853.tar.bz2
Remap-7d62cd890cb44945e772e18cdb457b1173f4f853.zip
Start adding tests
-rw-r--r--build.gradle.kts11
-rw-r--r--src/test/java/a/pkg/A.java31
-rw-r--r--src/test/java/a/pkg/AInterface.java5
-rw-r--r--src/test/java/a/pkg/AParent.java4
-rw-r--r--src/test/java/b/pkg/B.java31
-rw-r--r--src/test/java/b/pkg/BInterface.java5
-rw-r--r--src/test/java/b/pkg/BParent.java4
-rw-r--r--src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAccessors.kt65
-rw-r--r--src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAnnotation.kt52
-rw-r--r--src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinInjections.kt98
-rw-r--r--src/test/kotlin/com/replaymod/gradle/remap/util/TestData.kt48
-rw-r--r--src/test/kotlin/com/replaymod/gradle/remap/util/mappingExtensions.kt13
-rw-r--r--src/test/resources/mappings.srg13
13 files changed, 380 insertions, 0 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index 8032171..738d008 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -14,12 +14,19 @@ version = "SNAPSHOT"
repositories {
mavenCentral()
+ maven("https://repo.spongepowered.org/repository/maven-public/")
}
dependencies {
api("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.5.21")
implementation(kotlin("stdlib"))
api("org.cadixdev:lorenz:0.5.0")
+ runtimeOnly("net.java.dev.jna:jna:5.10.0") // don't strictly need this but IDEA spams log without
+
+ testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
+ testImplementation("io.kotest:kotest-assertions-core:4.6.3")
+
+ testRuntimeOnly("org.spongepowered:mixin:0.8.4")
}
tasks.named<Jar>("jar") {
@@ -33,3 +40,7 @@ publishing {
}
}
}
+
+tasks.test {
+ useJUnitPlatform()
+}
diff --git a/src/test/java/a/pkg/A.java b/src/test/java/a/pkg/A.java
new file mode 100644
index 0000000..d91a6e5
--- /dev/null
+++ b/src/test/java/a/pkg/A.java
@@ -0,0 +1,31 @@
+package a.pkg;
+
+public class A extends AParent implements AInterface {
+ private int aField;
+
+ public void aMethod() {
+ }
+
+ public void aOverloaded() {
+ }
+
+ public void aOverloaded(int arg) {
+ }
+
+ public void aOverloaded(boolean arg) {
+ }
+
+ public void commonOverloaded(Object arg) {
+ }
+
+ public void commonOverloaded(A arg) {
+ }
+
+ @Override
+ public void aInterfaceMethod() {
+ }
+
+ public class Inner {
+ private int aField;
+ }
+}
diff --git a/src/test/java/a/pkg/AInterface.java b/src/test/java/a/pkg/AInterface.java
new file mode 100644
index 0000000..8786c94
--- /dev/null
+++ b/src/test/java/a/pkg/AInterface.java
@@ -0,0 +1,5 @@
+package a.pkg;
+
+public interface AInterface {
+ void aInterfaceMethod();
+}
diff --git a/src/test/java/a/pkg/AParent.java b/src/test/java/a/pkg/AParent.java
new file mode 100644
index 0000000..aaf35fb
--- /dev/null
+++ b/src/test/java/a/pkg/AParent.java
@@ -0,0 +1,4 @@
+package a.pkg;
+
+public class AParent {
+}
diff --git a/src/test/java/b/pkg/B.java b/src/test/java/b/pkg/B.java
new file mode 100644
index 0000000..48abdac
--- /dev/null
+++ b/src/test/java/b/pkg/B.java
@@ -0,0 +1,31 @@
+package b.pkg;
+
+public class B extends BParent implements BInterface {
+ private int bField;
+
+ public void bMethod() {
+ }
+
+ public void bOverloaded() {
+ }
+
+ public void bOverloaded(int arg) {
+ }
+
+ public void bOverloaded(boolean arg) {
+ }
+
+ public void commonOverloaded(Object arg) {
+ }
+
+ public void commonOverloaded(B arg) {
+ }
+
+ @Override
+ public void bInterfaceMethod() {
+ }
+
+ public class Inner {
+ private int bField;
+ }
+}
diff --git a/src/test/java/b/pkg/BInterface.java b/src/test/java/b/pkg/BInterface.java
new file mode 100644
index 0000000..c57c72f
--- /dev/null
+++ b/src/test/java/b/pkg/BInterface.java
@@ -0,0 +1,5 @@
+package b.pkg;
+
+public interface BInterface {
+ void bInterfaceMethod();
+}
diff --git a/src/test/java/b/pkg/BParent.java b/src/test/java/b/pkg/BParent.java
new file mode 100644
index 0000000..29cae54
--- /dev/null
+++ b/src/test/java/b/pkg/BParent.java
@@ -0,0 +1,4 @@
+package b.pkg;
+
+public class BParent {
+}
diff --git a/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAccessors.kt b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAccessors.kt
new file mode 100644
index 0000000..4b9450f
--- /dev/null
+++ b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAccessors.kt
@@ -0,0 +1,65 @@
+package com.replaymod.gradle.remap.mapper
+
+import com.replaymod.gradle.remap.util.TestData
+import io.kotest.matchers.shouldBe
+import org.junit.jupiter.api.Test
+
+class TestMixinAccessors {
+ @Test
+ fun `remaps @Invoker`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ interface MixinA {
+ @org.spongepowered.asm.mixin.gen.Invoker
+ void invokeAMethod();
+ @org.spongepowered.asm.mixin.gen.Invoker("aMethod")
+ void invokeBMethod();
+ }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ interface MixinA {
+ @org.spongepowered.asm.mixin.gen.Invoker("bMethod")
+ void invokeAMethod();
+ @org.spongepowered.asm.mixin.gen.Invoker
+ void invokeBMethod();
+ }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps @Accessor`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ interface MixinA {
+ @org.spongepowered.asm.mixin.gen.Accessor
+ int isAField();
+ @org.spongepowered.asm.mixin.gen.Accessor
+ int getAField();
+ @org.spongepowered.asm.mixin.gen.Accessor
+ void setAField(int value);
+ @org.spongepowered.asm.mixin.gen.Accessor("aField")
+ int isBField();
+ @org.spongepowered.asm.mixin.gen.Accessor("aField")
+ int getBField();
+ @org.spongepowered.asm.mixin.gen.Accessor("aField")
+ void setBField(int value);
+ }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ interface MixinA {
+ @org.spongepowered.asm.mixin.gen.Accessor("bField")
+ int isAField();
+ @org.spongepowered.asm.mixin.gen.Accessor("bField")
+ int getAField();
+ @org.spongepowered.asm.mixin.gen.Accessor("bField")
+ void setAField(int value);
+ @org.spongepowered.asm.mixin.gen.Accessor
+ int isBField();
+ @org.spongepowered.asm.mixin.gen.Accessor
+ int getBField();
+ @org.spongepowered.asm.mixin.gen.Accessor
+ void setBField(int value);
+ }
+ """.trimIndent()
+ }
+} \ No newline at end of file
diff --git a/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAnnotation.kt b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAnnotation.kt
new file mode 100644
index 0000000..1f9a3a2
--- /dev/null
+++ b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinAnnotation.kt
@@ -0,0 +1,52 @@
+package com.replaymod.gradle.remap.mapper
+
+import com.replaymod.gradle.remap.util.TestData
+import io.kotest.matchers.shouldBe
+import org.junit.jupiter.api.Test
+
+class TestMixinAnnotation {
+ @Test
+ fun `remaps with class target`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ class MixinA { @Shadow private int aField; }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ class MixinA { @Shadow private int bField; }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps with string target`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(targets = "a.pkg.A")
+ class MixinA { @Shadow private int aField; }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(targets = "b.pkg.B")
+ class MixinA { @Shadow private int bField; }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps with inner class string target separated by dot`() {
+ // FIXME should probably keep the dot?
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(targets = "a.pkg.A.Inner")
+ class MixinA { @Shadow private int aField; }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(targets = "b.pkg.B${'$'}Inner")
+ class MixinA { @Shadow private int bField; }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps with inner class string target separated by dollar`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(targets = "a.pkg.A${'$'}Inner")
+ class MixinA { @Shadow private int aField; }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(targets = "b.pkg.B${'$'}Inner")
+ class MixinA { @Shadow private int bField; }
+ """.trimIndent()
+ }
+} \ No newline at end of file
diff --git a/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinInjections.kt b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinInjections.kt
new file mode 100644
index 0000000..856b56e
--- /dev/null
+++ b/src/test/kotlin/com/replaymod/gradle/remap/mapper/TestMixinInjections.kt
@@ -0,0 +1,98 @@
+package com.replaymod.gradle.remap.mapper
+
+import com.replaymod.gradle.remap.util.TestData
+import io.kotest.matchers.collections.shouldHaveSize
+import io.kotest.matchers.shouldBe
+import io.kotest.matchers.string.shouldContain
+import org.junit.jupiter.api.Test
+
+class TestMixinInjections {
+ private fun remaps(annotation: String) {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ class MixinA {
+ @$annotation(method = "aMethod")
+ private void test() {}
+ }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ class MixinA {
+ @$annotation(method = "bMethod")
+ private void test() {}
+ }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps @Inject method`() = remaps("org.spongepowered.asm.mixin.injection.Inject")
+
+ @Test
+ fun `remaps @ModifyArg method`() = remaps("org.spongepowered.asm.mixin.injection.ModifyArg")
+
+ @Test
+ fun `remaps @ModifyArgs method`() = remaps("org.spongepowered.asm.mixin.injection.ModifyArgs")
+
+ @Test
+ fun `remaps @ModifyConstant method`() = remaps("org.spongepowered.asm.mixin.injection.ModifyConstant")
+
+ @Test
+ fun `remaps @ModifyVariable method`() = remaps("org.spongepowered.asm.mixin.injection.ModifyVariable")
+
+ @Test
+ fun `remaps @Redirect method`() = remaps("org.spongepowered.asm.mixin.injection.Redirect")
+
+ @Test
+ fun `throws when injecting into ambiguous method`() {
+ val (_, errors) = TestData.remapWithErrors("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ class MixinA {
+ @org.spongepowered.asm.mixin.injection.Inject(method = "aOverloaded")
+ private void test() {}
+ }
+ """.trimIndent())
+ errors shouldHaveSize 1
+ val (line, error) = errors[0]
+ line shouldBe 2
+ error shouldContain "aOverloaded"
+ error shouldContain "(I)V"
+ error shouldContain "(Z)V"
+ }
+
+ @Test
+ fun `remaps qualified method`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ class MixinA {
+ @org.spongepowered.asm.mixin.injection.Inject(method = "aOverloaded()V")
+ private void test() {}
+ @org.spongepowered.asm.mixin.injection.Inject(method = "aOverloaded(I)V")
+ private void testArg() {}
+ }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ class MixinA {
+ @org.spongepowered.asm.mixin.injection.Inject(method = "bOverloaded()V")
+ private void test() {}
+ @org.spongepowered.asm.mixin.injection.Inject(method = "bOverloaded(I)V")
+ private void testArg() {}
+ }
+ """.trimIndent()
+ }
+
+ @Test
+ fun `remaps qualified method argument`() {
+ TestData.remap("""
+ @org.spongepowered.asm.mixin.Mixin(a.pkg.A.class)
+ class MixinA {
+ @org.spongepowered.asm.mixin.injection.Inject(method = "commonOverloaded(La/pkg/A;)V")
+ private void test() {}
+ }
+ """.trimIndent()) shouldBe """
+ @org.spongepowered.asm.mixin.Mixin(b.pkg.B.class)
+ class MixinA {
+ @org.spongepowered.asm.mixin.injection.Inject(method = "commonOverloaded(Lb/pkg/B;)V")
+ private void test() {}
+ }
+ """.trimIndent()
+ }
+} \ No newline at end of file
diff --git a/src/test/kotlin/com/replaymod/gradle/remap/util/TestData.kt b/src/test/kotlin/com/replaymod/gradle/remap/util/TestData.kt
new file mode 100644
index 0000000..cb0ad44
--- /dev/null
+++ b/src/test/kotlin/com/replaymod/gradle/remap/util/TestData.kt
@@ -0,0 +1,48 @@
+package com.replaymod.gradle.remap.util
+
+import com.replaymod.gradle.remap.Transformer
+import com.replaymod.gradle.remap.legacy.LegacyMappingSetModelFactory
+import org.cadixdev.lorenz.MappingSet
+import java.net.URL
+import java.nio.file.Paths
+import kotlin.io.path.absolutePathString
+
+object TestData {
+ private val mappingsPath = Paths.get(javaClass.getResource("/mappings.srg")!!.toURI())
+ private val mappings = mappingsPath.readMappings().let { mappings ->
+ val legacyCopy = MappingSet.create(LegacyMappingSetModelFactory())
+ mappings.topLevelClassMappings.forEach { it.copy(legacyCopy) }
+ legacyCopy
+ }
+
+ val transformer = Transformer(mappings).apply {
+ fun findClasspathEntry(cls: String): String {
+ val classFilePath = "/${cls.replace('.', '/')}.class"
+ val url = javaClass.getResource(classFilePath)
+ ?: throw RuntimeException("Failed to find $cls on classpath.")
+
+ return when {
+ url.protocol == "jar" && url.file.endsWith("!$classFilePath") -> {
+ Paths.get(URL(url.file.removeSuffix("!$classFilePath")).toURI()).absolutePathString()
+ }
+ url.protocol == "file" && url.file.endsWith(classFilePath) -> {
+ var path = Paths.get(url.toURI())
+ repeat(cls.count { it == '.' } + 1) {
+ path = path.parent
+ }
+ path.absolutePathString()
+ }
+ else -> {
+ throw RuntimeException("Do not know how to turn $url into classpath entry.")
+ }
+ }
+ }
+ classpath = arrayOf(
+ findClasspathEntry("org.spongepowered.asm.mixin.Mixin"),
+ findClasspathEntry("a.pkg.A"),
+ )
+ }
+
+ fun remap(content: String): String = transformer.remap(mapOf("test.java" to content))["test.java"]!!.first
+ fun remapWithErrors(content: String) = transformer.remap(mapOf("test.java" to content))["test.java"]!!
+} \ No newline at end of file
diff --git a/src/test/kotlin/com/replaymod/gradle/remap/util/mappingExtensions.kt b/src/test/kotlin/com/replaymod/gradle/remap/util/mappingExtensions.kt
new file mode 100644
index 0000000..9a869d4
--- /dev/null
+++ b/src/test/kotlin/com/replaymod/gradle/remap/util/mappingExtensions.kt
@@ -0,0 +1,13 @@
+package com.replaymod.gradle.remap.util
+
+import org.cadixdev.lorenz.MappingSet
+import org.cadixdev.lorenz.io.MappingFormats
+import java.nio.file.Path
+
+fun Path.readMappings(): MappingSet {
+ val name = fileName.toString()
+ val ext = name.substring(name.lastIndexOf(".") + 1)
+ val format = MappingFormats.REGISTRY.values().find { it.standardFileExtension.orElse(null) == ext }
+ ?: throw UnsupportedOperationException("Cannot find mapping format for $this")
+ return format.read(this)
+}
diff --git a/src/test/resources/mappings.srg b/src/test/resources/mappings.srg
new file mode 100644
index 0000000..22d63a9
--- /dev/null
+++ b/src/test/resources/mappings.srg
@@ -0,0 +1,13 @@
+CL: a/pkg/A b/pkg/B
+FD: a/pkg/A/aField b/pkg/B/bField
+MD: a/pkg/A/aMethod ()V b/pkg/B/bMethod ()V
+MD: a/pkg/A/aOverloaded ()V b/pkg/B/bOverloaded ()V
+MD: a/pkg/A/aOverloaded (I)V b/pkg/B/bOverloaded (I)V
+MD: a/pkg/A/aOverloaded (Z)V b/pkg/B/bOverloaded (Z)V
+MD: a/pkg/A/commonOverloaded (Ljava/lang/Object;)V b/pkg/B/commonOverloaded (Ljava/lang/Object;)V
+MD: a/pkg/A/commonOverloaded (La/pkg/A;)V b/pkg/B/commonOverloaded (La/pkg/B;)V
+CL: a/pkg/A$Inner b/pkg/B$Inner
+FD: a/pkg/A$Inner/aField b/pkg/B$Inner/bField
+CL: a/pkg/AParent b/pkg/BParent
+CL: a/pkg/AInterface b/pkg/BInterface
+MD: a/pkg/AInterface/aInterfaceMethod ()V b/pkg/BInterface/bInterfaceMethod ()V