From 41ccca86e17b3bd519823c6567a3f2528b6e6a6c Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Tue, 19 Dec 2023 14:20:29 +0100 Subject: [PATCH] mod loading test, fix infinite loading --- .../modding/loader/phase/LoadingPhaseTest.kt | 87 ++++++++++++++++++ .../resources/mods/broken/dummy/manifest.json | 1 + .../minosoft/modding/dummy/DummyMod.class | Bin 0 -> 1668 bytes .../minosoft/modding/dummy/DummyMod.kt | 30 ++++++ .../resources/mods/dummy/dummy/manifest.json | 6 ++ .../resources/mods/nocode/dummy/manifest.json | 6 ++ .../minosoft/modding/loader/ModList.kt | 8 +- .../modding/loader/phase/LoadingPhase.kt | 7 +- 8 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/integration-test/kotlin/de/bixilon/minosoft/modding/loader/phase/LoadingPhaseTest.kt create mode 100644 src/integration-test/resources/mods/broken/dummy/manifest.json create mode 100644 src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.class create mode 100644 src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.kt create mode 100644 src/integration-test/resources/mods/dummy/dummy/manifest.json create mode 100644 src/integration-test/resources/mods/nocode/dummy/manifest.json diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/modding/loader/phase/LoadingPhaseTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/modding/loader/phase/LoadingPhaseTest.kt new file mode 100644 index 0000000000..c0e23f7082 --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/modding/loader/phase/LoadingPhaseTest.kt @@ -0,0 +1,87 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.modding.loader.phase + +import de.bixilon.kutil.cast.CastUtil.unsafeCast +import de.bixilon.kutil.latch.SimpleLatch +import de.bixilon.kutil.reflection.ReflectionUtil.forceSet +import de.bixilon.kutil.reflection.ReflectionUtil.getFieldOrNull +import de.bixilon.minosoft.modding.loader.ModLoader +import de.bixilon.minosoft.terminal.RunConfiguration +import org.testng.Assert.assertEquals +import org.testng.annotations.Test +import java.io.File + + +@Test(groups = ["mods"]) +class LoadingPhaseTest { + + private fun create(path: String): LoadingPhase { + ModLoader.mods.clear() + val phase = LoadingPhase(path) + phase::class.java.getFieldOrNull("path")!!.forceSet(phase, File("./src/integration-test/resources/mods/$path")) + + return phase + } + + private val LoadingPhase.latch: SimpleLatch get() = this::class.java.getFieldOrNull("latch")!!.get(this).unsafeCast() + + fun setup() { + val phase = create("empty") + assertEquals(phase.state, PhaseStates.WAITING) + assertEquals(phase.latch.count, 1) // not started + } + + fun `load but skip loading`() { + val phase = create("empty") + RunConfiguration.IGNORE_MODS = true + phase.load() + RunConfiguration.IGNORE_MODS = false + phase.latch.await() + } + + fun `load empty`() { + val phase = create("empty") + phase.load() + assertEquals(phase.state, PhaseStates.COMPLETE) + assertEquals(phase.latch.count, 0) + phase.await() + assertEquals(ModLoader.mods.mods.size, 0) + } + + fun `broken mod`() { + val phase = create("broken") + phase.load() + phase.await() + assertEquals(ModLoader.mods.mods.size, 0) + } + + fun `nocode mod`() { + val phase = create("nocode") + phase.load() + phase.await() + assertEquals(ModLoader.mods.mods.size, 0) + } + + fun `dummy mod`() { + val phase = create("dummy") + phase.load() + phase.await() + assertEquals(ModLoader.mods.mods.size, 1) + val mod = ModLoader.mods["dummy"]!!.main!! + assertEquals(mod::class.java.getFieldOrNull("dummy")!!.get(mod), 1) + assertEquals(mod::class.java.getFieldOrNull("init")!!.get(mod), 1) + assertEquals(mod::class.java.getFieldOrNull("postInit")!!.get(mod), 1) + } +} diff --git a/src/integration-test/resources/mods/broken/dummy/manifest.json b/src/integration-test/resources/mods/broken/dummy/manifest.json new file mode 100644 index 0000000000..054032de4e --- /dev/null +++ b/src/integration-test/resources/mods/broken/dummy/manifest.json @@ -0,0 +1 @@ +Intentionally bad formatted diff --git a/src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.class b/src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.class new file mode 100644 index 0000000000000000000000000000000000000000..eb1507c03f0066075901142d5049ca61061f49b8 GIT binary patch literal 1668 zcmaJ?-*3}a6#njwlQ>SAI$eLJEil+d+d@zG z-ulEJvZra<%jg3VNT}-G_@kzM*G@|oLZ!s#+izwC9X<# z-7pJw@v>o>c8Ot483>ota3u}vJOkls8XmPvCw~-bTJf5|%DMf2f2epCtlvBxSGM7F zM3)cP(%G$Ul!WcTjh=)m+-(JS-W@R;elPX|fzd`71PFz^w+;2$;&;m@dEZ=T=#Rw`?$s#w}vrt zG`m zl`ub4!rY*QjQk-9g7?R17uR`G`Y_8cFtssj{B(rAdi2Erj)=uOfyj%zy*3fHl`gE0k5!BNO76ck1jRuu0=R1|7TM<*1<6{Z#H L3Ns4xDPZ+Kc*qa6 literal 0 HcmV?d00001 diff --git a/src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.kt b/src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.kt new file mode 100644 index 0000000000..fe4fe564ab --- /dev/null +++ b/src/integration-test/resources/mods/dummy/dummy/de/bixilon/minosoft/modding/dummy/DummyMod.kt @@ -0,0 +1,30 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.modding.dummy + +import de.bixilon.minosoft.modding.loader.mod.ModMain + +object DummyMod : ModMain() { + var dummy = 1 + var init = 0 + var postInit = 0 + + override fun init() { + init++ + } + + override fun postInit() { + postInit++ + } +} diff --git a/src/integration-test/resources/mods/dummy/dummy/manifest.json b/src/integration-test/resources/mods/dummy/dummy/manifest.json new file mode 100644 index 0000000000..491805904a --- /dev/null +++ b/src/integration-test/resources/mods/dummy/dummy/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "dummy", + "version": "1.0", + "main": "de.bixilon.minosoft.modding.dummy.DummyMod" +} + diff --git a/src/integration-test/resources/mods/nocode/dummy/manifest.json b/src/integration-test/resources/mods/nocode/dummy/manifest.json new file mode 100644 index 0000000000..0d92bb9e08 --- /dev/null +++ b/src/integration-test/resources/mods/nocode/dummy/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "dummy", + "version": "1.0", + "main": "de.bixilon.minosoft.modding.dummy.DummyNotExistant" +} + diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt b/src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt index 003563b29f..626a3c81e7 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt +++ b/src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -74,6 +74,12 @@ class ModList( this.virtual += list.virtual } + @Synchronized + fun clear() { + this.mods.clear() + this.virtual.clear() + } + override fun iterator(): Iterator { return mods.values.iterator() } diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/phase/LoadingPhase.kt b/src/main/java/de/bixilon/minosoft/modding/loader/phase/LoadingPhase.kt index 1e4fa87d1a..91470d2379 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loader/phase/LoadingPhase.kt +++ b/src/main/java/de/bixilon/minosoft/modding/loader/phase/LoadingPhase.kt @@ -22,6 +22,7 @@ import de.bixilon.kutil.observer.DataObserver.Companion.observed import de.bixilon.minosoft.modding.loader.ModList import de.bixilon.minosoft.modding.loader.ModLoader import de.bixilon.minosoft.modding.loader.ModLoadingUtil.construct +import de.bixilon.minosoft.modding.loader.ModLoadingUtil.postInit import de.bixilon.minosoft.modding.loader.ModLoadingUtil.validate import de.bixilon.minosoft.modding.loader.error.DuplicateModError import de.bixilon.minosoft.modding.loader.error.DuplicateProvidedError @@ -40,10 +41,6 @@ class LoadingPhase(val name: String) { var state by observed(PhaseStates.WAITING) private set - private fun MinosoftMod.postInit() { - main!!.postInit() - } - private fun inject(list: ModList, source: ModSource, latch: AbstractLatch) { val mod = MinosoftMod(source, this, ParentLatch(4, latch)) Log.log(LogMessageType.MOD_LOADING, LogLevels.VERBOSE) { "Injecting $source" } @@ -97,7 +94,7 @@ class LoadingPhase(val name: String) { if (files.isEmpty() && additionalSources.isEmpty()) { // no mods to load state = PhaseStates.COMPLETE - this.latch.dec() + inner.dec(); this.latch.dec() return } val list = ModList()