test: Switch to kotest & test mixins

This commit is contained in:
Linnea Gräf
2025-05-10 14:22:53 +02:00
parent 3cd70b1b1e
commit 6e06fa744d
14 changed files with 198 additions and 138 deletions

View File

@@ -317,8 +317,8 @@ dependencies {
} }
testImplementation("io.kotest:kotest-runner-junit5:6.0.0.M1") testImplementation("net.fabricmc:fabric-loader-junit:${libs.versions.fabric.loader.get()}")
testAgent(project(":testagent", configuration = "shadow")) testAgent(files(tasks.getByPath(":testagent:jar")))
implementation(projects.symbols) implementation(projects.symbols)
ksp(projects.symbols) ksp(projects.symbols)

View File

@@ -151,8 +151,8 @@ runtime_optional = [
"devauth", "devauth",
# "freecammod", # "freecammod",
# "sodium", # "sodium",
# "qolify", # "qolify",
"ncr", # "ncr",
# "citresewn", # "citresewn",
] ]

View File

@@ -8,56 +8,69 @@ import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MixinPlugin implements IMixinConfigPlugin { public class MixinPlugin implements IMixinConfigPlugin {
AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin(); AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
public static List<MixinPlugin> instances = new ArrayList<>(); public static List<MixinPlugin> instances = new ArrayList<>();
public String mixinPackage; public String mixinPackage;
@Override
public void onLoad(String mixinPackage) { @Override
MixinExtrasBootstrap.init(); public void onLoad(String mixinPackage) {
MixinExtrasBootstrap.init();
instances.add(this); instances.add(this);
this.mixinPackage = mixinPackage; this.mixinPackage = mixinPackage;
autoDiscoveryPlugin.setMixinPackage(mixinPackage); autoDiscoveryPlugin.setMixinPackage(mixinPackage);
} }
@Override @Override
public String getRefMapperConfig() { public String getRefMapperConfig() {
return null; return null;
} }
@Override @Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) { if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) {
return false; return false;
} }
return true; return true;
} }
@Override @Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
} }
@Override @Override
public List<String> getMixins() { public List<String> getMixins() {
return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it)) return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it))
.toList(); .toList();
} }
@Override @Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
} }
public List<String> appliedMixins = new ArrayList<>(); public Set<String> getAppliedFullPathMixins() {
return new HashSet<>(appliedMixins);
}
@Override public Set<String> getExpectedFullPathMixins() {
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { return getMixins()
appliedMixins.add(mixinClassName); .stream()
} .map(it -> mixinPackage + "." + it)
.collect(Collectors.toSet());
}
public List<String> appliedMixins = new ArrayList<>();
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
appliedMixins.add(mixinClassName);
}
} }

View File

@@ -9,6 +9,7 @@ import io.github.notenoughupdates.moulconfig.gui.GuiContext
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
import io.github.notenoughupdates.moulconfig.gui.MouseEvent import io.github.notenoughupdates.moulconfig.gui.MouseEvent
import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
import io.github.notenoughupdates.moulconfig.observer.GetSetter import io.github.notenoughupdates.moulconfig.observer.GetSetter
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
import io.github.notenoughupdates.moulconfig.xml.ChildCount import io.github.notenoughupdates.moulconfig.xml.ChildCount
@@ -20,6 +21,7 @@ import java.io.File
import java.util.function.Supplier import java.util.function.Supplier
import javax.xml.namespace.QName import javax.xml.namespace.QName
import me.shedaniel.math.Color import me.shedaniel.math.Color
import org.jetbrains.annotations.Unmodifiable
import org.w3c.dom.Element import org.w3c.dom.Element
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds

View File

@@ -0,0 +1,34 @@
package moe.nea.firmament.test
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.spongepowered.asm.mixin.MixinEnvironment
import org.spongepowered.asm.mixin.transformer.IMixinTransformer
import moe.nea.firmament.init.MixinPlugin
class MixinTest {
@Test
fun mixinAudit() {
FirmTestBootstrap.bootstrapMinecraft()
MixinEnvironment.getCurrentEnvironment().audit()
val mp = MixinPlugin.instances.single()
Assertions.assertEquals(
mp.expectedFullPathMixins,
mp.appliedFullPathMixins,
)
Assertions.assertNotEquals(
0,
mp.mixins.size
)
}
@Test
fun hasInstalledMixinTransformer() {
Assertions.assertInstanceOf(
IMixinTransformer::class.java,
MixinEnvironment.getCurrentEnvironment().activeTransformer
)
}
}

View File

@@ -24,6 +24,7 @@ object FirmTestBootstrap {
println("Bootstrap completed at $loadEnd after $loadDuration") println("Bootstrap completed at $loadEnd after $loadDuration")
} }
@JvmStatic
fun bootstrapMinecraft() { fun bootstrapMinecraft() {
} }
} }

View File

@@ -0,0 +1,14 @@
package moe.nea.firmament.test.testutil
import com.google.auto.service.AutoService
import org.junit.jupiter.api.extension.BeforeAllCallback
import org.junit.jupiter.api.extension.Extension
import org.junit.jupiter.api.extension.ExtensionContext
import moe.nea.firmament.test.FirmTestBootstrap
@AutoService(Extension::class)
class AutoBootstrapExtension : Extension, BeforeAllCallback {
override fun beforeAll(p0: ExtensionContext) {
FirmTestBootstrap.bootstrapMinecraft()
}
}

View File

@@ -1,16 +0,0 @@
package moe.nea.firmament.test.testutil
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.extensions.Extension
import moe.nea.firmament.test.FirmTestBootstrap
class KotestPlugin : AbstractProjectConfig() {
override fun extensions(): List<Extension> {
return listOf()
}
override suspend fun beforeProject() {
FirmTestBootstrap.bootstrapMinecraft()
super.beforeProject()
}
}

View File

@@ -1,57 +1,57 @@
package moe.nea.firmament.test.util package moe.nea.firmament.test.util
import io.kotest.core.spec.style.AnnotationSpec
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import moe.nea.firmament.util.removeColorCodes import moe.nea.firmament.util.removeColorCodes
class ColorCodeTest : AnnotationSpec() { class ColorCodeTest {
@Test @Test
fun testWhatever() { fun testWhatever() {
Assertions.assertEquals("", "".removeColorCodes()) Assertions.assertEquals("", "".removeColorCodes())
Assertions.assertEquals("", "§".removeColorCodes()) Assertions.assertEquals("", "§".removeColorCodes())
Assertions.assertEquals("", "§a".removeColorCodes()) Assertions.assertEquals("", "§a".removeColorCodes())
Assertions.assertEquals("ab", "a§ab".removeColorCodes()) Assertions.assertEquals("ab", "a§ab".removeColorCodes())
Assertions.assertEquals("ab", "a§ab§§".removeColorCodes()) Assertions.assertEquals("ab", "a§ab§§".removeColorCodes())
Assertions.assertEquals("abc", "a§ab§§c".removeColorCodes()) Assertions.assertEquals("abc", "a§ab§§c".removeColorCodes())
Assertions.assertEquals("bc", "§ab§§c".removeColorCodes()) Assertions.assertEquals("bc", "§ab§§c".removeColorCodes())
Assertions.assertEquals("b§lc", "§ab§l§§c".removeColorCodes(true)) Assertions.assertEquals("b§lc", "§ab§l§§c".removeColorCodes(true))
Assertions.assertEquals("b§lc§l", "§ab§l§§c§l".removeColorCodes(true)) Assertions.assertEquals("b§lc§l", "§ab§l§§c§l".removeColorCodes(true))
Assertions.assertEquals("§lb§lc", "§l§ab§l§§c".removeColorCodes(true)) Assertions.assertEquals("§lb§lc", "§l§ab§l§§c".removeColorCodes(true))
} }
@Test @Test
fun testEdging() { fun testEdging() {
Assertions.assertEquals("", "§".removeColorCodes()) Assertions.assertEquals("", "§".removeColorCodes())
Assertions.assertEquals("a", "".removeColorCodes()) Assertions.assertEquals("a", "".removeColorCodes())
Assertions.assertEquals("b", "§ab§".removeColorCodes()) Assertions.assertEquals("b", "§ab§".removeColorCodes())
} }
@Test @Test
fun `testDouble§`() { fun `testDouble§`() {
Assertions.assertEquals("1", "§§1".removeColorCodes()) Assertions.assertEquals("1", "§§1".removeColorCodes())
} }
@Test @Test
fun testKeepNonColor() { fun testKeepNonColor() {
Assertions.assertEquals("§k§l§m§n§o§r", "§k§l§m§f§n§o§r".removeColorCodes(true)) Assertions.assertEquals("§k§l§m§n§o§r", "§k§l§m§f§n§o§r".removeColorCodes(true))
} }
@Test @Test
fun testPlainString() { fun testPlainString() {
Assertions.assertEquals("bcdefgp", "bcdefgp".removeColorCodes()) Assertions.assertEquals("bcdefgp", "bcdefgp".removeColorCodes())
Assertions.assertEquals("", "".removeColorCodes()) Assertions.assertEquals("", "".removeColorCodes())
} }
@Test @Test
fun testSomeNormalTestCases() { fun testSomeNormalTestCases() {
Assertions.assertEquals( Assertions.assertEquals(
"You are not currently in a party.", "You are not currently in a party.",
"§r§cYou are not currently in a party.§r".removeColorCodes() "§r§cYou are not currently in a party.§r".removeColorCodes()
) )
Assertions.assertEquals( Assertions.assertEquals(
"Ancient Necron's Chestplate ✪✪✪✪", "Ancient Necron's Chestplate ✪✪✪✪",
"§dAncient Necron's Chestplate §6✪§6✪§6✪§6✪".removeColorCodes() "§dAncient Necron's Chestplate §6✪§6✪§6✪§6✪".removeColorCodes()
) )
} }
} }

View File

@@ -1,16 +1,18 @@
package moe.nea.firmament.test.util package moe.nea.firmament.test.util
import io.kotest.core.spec.style.AnnotationSpec
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import moe.nea.firmament.test.testutil.ItemResources import moe.nea.firmament.test.testutil.ItemResources
import moe.nea.firmament.util.getLegacyFormatString import moe.nea.firmament.util.getLegacyFormatString
class TextUtilText : AnnotationSpec() { class TextUtilText {
@Test @Test
fun testThing() { fun testThing() {
// TODO: add more tests that are directly validated with 1.8.9 code // TODO: add more tests that are directly validated with 1.8.9 code
val text = ItemResources.loadText("all-chat") val text = ItemResources.loadText("all-chat")
Assertions.assertEquals("§r§r§8[§r§9302§r§8] §r§6♫ §r§b[MVP§r§d+§r§b] lrg89§r§f: test§r", Assertions.assertEquals(
text.getLegacyFormatString()) "§r§r§8[§r§9302§r§8] §r§6♫ §r§b[MVP§r§d+§r§b] lrg89§r§f: test§r",
text.getLegacyFormatString()
)
} }
} }

View File

@@ -1,12 +1,12 @@
package moe.nea.firmament.test.util.math package moe.nea.firmament.test.util.math
import io.kotest.core.spec.style.AnnotationSpec
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import moe.nea.firmament.util.math.GChainReconciliation import moe.nea.firmament.util.math.GChainReconciliation
import moe.nea.firmament.util.math.GChainReconciliation.rotated import moe.nea.firmament.util.math.GChainReconciliation.rotated
class GChainReconciliationTest : AnnotationSpec() { class GChainReconciliationTest {
fun <T> assertEqualCycles( fun <T> assertEqualCycles(
expected: List<T>, expected: List<T>,

View File

@@ -1,7 +1,7 @@
package moe.nea.firmament.test.util.skyblock package moe.nea.firmament.test.util.skyblock
import io.kotest.core.spec.style.AnnotationSpec
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
import net.minecraft.text.Text import net.minecraft.text.Text
@@ -9,7 +9,7 @@ import moe.nea.firmament.test.testutil.ItemResources
import moe.nea.firmament.util.skyblock.AbilityUtils import moe.nea.firmament.util.skyblock.AbilityUtils
import moe.nea.firmament.util.unformattedString import moe.nea.firmament.util.unformattedString
class AbilityUtilsTest : AnnotationSpec() { class AbilityUtilsTest {
fun List<AbilityUtils.ItemAbility>.stripDescriptions() = map { fun List<AbilityUtils.ItemAbility>.stripDescriptions() = map {
it.copy(descriptionLines = it.descriptionLines.map { Text.literal(it.unformattedString) }) it.copy(descriptionLines = it.descriptionLines.map { Text.literal(it.unformattedString) })
@@ -24,9 +24,11 @@ class AbilityUtilsTest : AnnotationSpec() {
false, false,
AbilityUtils.AbilityActivation.RIGHT_CLICK, AbilityUtils.AbilityActivation.RIGHT_CLICK,
null, null,
listOf("Throw your pickaxe to create an", listOf(
"explosion mining all ores in a 3 block", "Throw your pickaxe to create an",
"radius.").map(Text::literal), "explosion mining all ores in a 3 block",
"radius."
).map(Text::literal),
48.seconds 48.seconds
) )
), ),
@@ -43,8 +45,10 @@ class AbilityUtilsTest : AnnotationSpec() {
true, true,
AbilityUtils.AbilityActivation.RIGHT_CLICK, AbilityUtils.AbilityActivation.RIGHT_CLICK,
null, null,
listOf("Grants +200% ⸕ Mining Speed for", listOf(
"10s.").map(Text::literal), "Grants +200% ⸕ Mining Speed for",
"10s."
).map(Text::literal),
2.minutes 2.minutes
) )
), ),
@@ -58,8 +62,10 @@ class AbilityUtilsTest : AnnotationSpec() {
listOf( listOf(
AbilityUtils.ItemAbility( AbilityUtils.ItemAbility(
"Instant Transmission", true, AbilityUtils.AbilityActivation.RIGHT_CLICK, 23, "Instant Transmission", true, AbilityUtils.AbilityActivation.RIGHT_CLICK, 23,
listOf("Teleport 12 blocks ahead of you and", listOf(
"gain +50 ✦ Speed for 3 seconds.").map(Text::literal), "Teleport 12 blocks ahead of you and",
"gain +50 ✦ Speed for 3 seconds."
).map(Text::literal),
null null
), ),
AbilityUtils.ItemAbility( AbilityUtils.ItemAbility(
@@ -67,9 +73,11 @@ class AbilityUtilsTest : AnnotationSpec() {
false, false,
AbilityUtils.AbilityActivation.SNEAK_RIGHT_CLICK, AbilityUtils.AbilityActivation.SNEAK_RIGHT_CLICK,
90, 90,
listOf("Teleport to your targeted block up", listOf(
"to 61 blocks away.", "Teleport to your targeted block up",
"Soulflow Cost: 1").map(Text::literal), "to 61 blocks away.",
"Soulflow Cost: 1"
).map(Text::literal),
null null
) )
), ),

View File

@@ -1,26 +1,28 @@
package moe.nea.firmament.test.util.skyblock package moe.nea.firmament.test.util.skyblock
import io.kotest.core.spec.style.ShouldSpec import org.junit.jupiter.api.Assertions
import io.kotest.matchers.shouldBe import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.TestFactory
import moe.nea.firmament.test.testutil.ItemResources import moe.nea.firmament.test.testutil.ItemResources
import moe.nea.firmament.util.skyblock.ItemType import moe.nea.firmament.util.skyblock.ItemType
class ItemTypeTest class ItemTypeTest {
: ShouldSpec( @TestFactory
{ fun fromItemstack() =
context("ItemType.fromItemstack") { listOf(
listOf( "pets/lion-item" to ItemType.PET,
"pets/lion-item" to ItemType.PET, "pets/rabbit-selected" to ItemType.PET,
"pets/rabbit-selected" to ItemType.PET, "pets/mithril-golem-not-selected" to ItemType.PET,
"pets/mithril-golem-not-selected" to ItemType.PET, "aspect-of-the-void" to ItemType.SWORD,
"aspect-of-the-void" to ItemType.SWORD, "titanium-drill" to ItemType.DRILL,
"titanium-drill" to ItemType.DRILL, "diamond-pickaxe" to ItemType.PICKAXE,
"diamond-pickaxe" to ItemType.PICKAXE, "gemstone-gauntlet" to ItemType.GAUNTLET,
"gemstone-gauntlet" to ItemType.GAUNTLET, ).map { (name, typ) ->
).forEach { (name, typ) -> DynamicTest.dynamicTest("return $typ for $name") {
should("return $typ for $name") { Assertions.assertEquals(
ItemType.fromItemStack(ItemResources.loadItem(name)) shouldBe typ typ,
} ItemType.fromItemStack(ItemResources.loadItem(name))
)
} }
} }
}) }

View File

@@ -1,12 +1,12 @@
package moe.nea.firmament.test.util.skyblock package moe.nea.firmament.test.util.skyblock
import io.kotest.core.spec.style.AnnotationSpec
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import moe.nea.firmament.test.testutil.ItemResources import moe.nea.firmament.test.testutil.ItemResources
import moe.nea.firmament.util.skyblock.SackUtil import moe.nea.firmament.util.skyblock.SackUtil
import moe.nea.firmament.util.skyblock.SkyBlockItems import moe.nea.firmament.util.skyblock.SkyBlockItems
class SackUtilTest : AnnotationSpec() { class SackUtilTest {
@Test @Test
fun testOneRottenFlesh() { fun testOneRottenFlesh() {
Assertions.assertEquals( Assertions.assertEquals(