profile manager tests

This commit is contained in:
Moritz Zwerger 2023-11-21 14:18:01 +01:00
parent b8a02311de
commit 1943a9f331
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 198 additions and 27 deletions

View File

@ -14,6 +14,7 @@
package de.bixilon.minosoft package de.bixilon.minosoft
import de.bixilon.kutil.latch.SimpleLatch import de.bixilon.kutil.latch.SimpleLatch
import de.bixilon.kutil.reflection.ReflectionUtil.forceSet
import de.bixilon.minosoft.assets.meta.MinosoftMeta import de.bixilon.minosoft.assets.meta.MinosoftMeta
import de.bixilon.minosoft.assets.properties.version.AssetsVersionProperties import de.bixilon.minosoft.assets.properties.version.AssetsVersionProperties
import de.bixilon.minosoft.data.registries.fallback.FallbackRegistries import de.bixilon.minosoft.data.registries.fallback.FallbackRegistries
@ -28,15 +29,24 @@ import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
import org.testng.annotations.BeforeSuite import org.testng.annotations.BeforeSuite
import java.nio.file.Path
internal object MinosoftSIT { internal object MinosoftSIT {
private fun setupEnv() {
Log.ASYNC_LOGGING = false
RunConfiguration.VERBOSE_LOGGING = true
RunConfiguration.APPLICATION_NAME = "Minosoft it"
RunConfiguration::HOME_DIRECTORY.forceSet(Path.of(System.getProperty("java.io.tmpdir"), "minosoft"))
RunConfiguration::CONFIG_DIRECTORY.forceSet(Path.of(System.getProperty("java.io.tmpdir"), "minosoft").resolve("conf"))
RunConfiguration.PROFILES_HOT_RELOADING = false
}
@BeforeSuite @BeforeSuite
fun setup() { fun setup() {
Log.ASYNC_LOGGING = false setupEnv()
Log.log(LogMessageType.OTHER, LogLevels.INFO) { "This is java version ${System.getProperty("java.version")}" } Log.log(LogMessageType.OTHER, LogLevels.INFO) { "This is java version ${System.getProperty("java.version")}" }
RunConfiguration.VERBOSE_LOGGING = true
KUtil.initBootClasses() KUtil.initBootClasses()
KUtil.initPlayClasses() KUtil.initPlayClasses()
disableGC() disableGC()

View File

@ -0,0 +1,22 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile
class Boxed(val value: Int, val assigned: Boolean) {
override fun equals(other: Any?): Boolean {
if (other !is Boxed) return false
return other.value == this.value
}
}

View File

@ -16,11 +16,9 @@ package de.bixilon.minosoft.config.profile.delegate.types
import com.fasterxml.jackson.databind.InjectableValues import com.fasterxml.jackson.databind.InjectableValues
import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.module.kotlin.convertValue import com.fasterxml.jackson.module.kotlin.convertValue
import de.bixilon.kutil.concurrent.lock.Lock
import de.bixilon.kutil.json.JsonObject import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.config.profile.ProfileLock import de.bixilon.minosoft.config.profile.Boxed
import de.bixilon.minosoft.config.profile.profiles.Profile import de.bixilon.minosoft.config.profile.test.TestProfile
import de.bixilon.minosoft.config.profile.storage.ProfileStorage
import de.bixilon.minosoft.util.json.Jackson import de.bixilon.minosoft.util.json.Jackson
import org.testng.Assert.assertEquals import org.testng.Assert.assertEquals
import org.testng.annotations.Test import org.testng.annotations.Test
@ -65,7 +63,8 @@ class RedirectDelegateTest {
fun `update redirect property`() { fun `update redirect property`() {
val profile = create() val profile = create()
assertEquals(profile.config.prop, null) assertEquals(profile.config.prop, null)
profile.update(mapOf("config" to mapOf("normal" to 12)))
profile.update(mapOf("config" to mapOf("prop" to 12)))
assertEquals(profile.config.prop, Boxed(12, false)) assertEquals(profile.config.prop, Boxed(12, false))
} }
@ -82,23 +81,4 @@ class RedirectDelegateTest {
} }
class TestProfile(
override var storage: ProfileStorage? = null,
override val lock: Lock = ProfileLock(),
) : Profile {
val config = TestConfig(this)
}
class TestConfig(profile: Profile) {
var prop by RedirectDelegate<Boxed?, Int?>(profile, { it?.value }, { it?.let { Boxed(it, false) } })
var normal by StringDelegate(profile, "test")
}
class Boxed(val value: Int, val unused: Boolean) {
override fun equals(other: Any?): Boolean {
if (other !is Boxed) return false
return other.value == this.value
}
}
} }

View File

@ -0,0 +1,46 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.storage
import de.bixilon.minosoft.config.profile.test.TestProfileManager
import de.bixilon.minosoft.protocol.ProtocolUtil.encodeNetwork
import de.bixilon.minosoft.terminal.RunConfiguration
import org.testng.Assert.assertEquals
import org.testng.annotations.Test
import java.io.FileOutputStream
@Test(groups = ["profiles"])
class StorageProfileManagerTest {
private val base by lazy { RunConfiguration.CONFIG_DIRECTORY.resolve("minosoft").resolve("test") }
private fun dump(name: String, data: String) {
val path = base.resolve("$name.json")
path.parent.toFile().mkdirs()
val stream = FileOutputStream(path.toFile())
stream.write(data.encodeNetwork())
stream.close()
}
fun `load dumped profiles`() {
val profile = """{"version": "1", "key_old": 123}"""
dump("Dumped", profile)
val manager = TestProfileManager()
assertEquals(manager["Dumped"], null)
manager.load()
val dumped = manager["Dumped"]!!
assertEquals(dumped.key, 123)
}
}

View File

@ -0,0 +1,40 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.test
import de.bixilon.kutil.concurrent.lock.Lock
import de.bixilon.minosoft.config.profile.ProfileLock
import de.bixilon.minosoft.config.profile.ProfileType
import de.bixilon.minosoft.config.profile.delegate.primitive.IntDelegate
import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.config.profile.storage.ProfileStorage
import de.bixilon.minosoft.config.profile.test.config.ConfigC
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
class TestProfile(
override var storage: ProfileStorage? = null,
override val lock: Lock = ProfileLock(),
) : Profile {
val config = ConfigC(this)
var key by IntDelegate(this, 1)
companion object : ProfileType<TestProfile> {
override val identifier = minosoft("test")
override val clazz = TestProfile::class.java
override fun create(storage: ProfileStorage?) = TestProfile(storage)
}
}

View File

@ -0,0 +1,32 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.test
import com.fasterxml.jackson.databind.node.ObjectNode
import de.bixilon.minosoft.config.profile.storage.StorageProfileManager
class TestProfileManager : StorageProfileManager<TestProfile>() {
override val type get() = TestProfile
override val latestVersion get() = 2
override fun migrate(version: Int, data: ObjectNode) = when (version) {
1 -> migrate1(data)
else -> Unit
}
fun migrate1(data: ObjectNode) {
data.remove("key_old")?.asInt()?.let { data.put("key", it) }
}
}

View File

@ -0,0 +1,26 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.test.config
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import de.bixilon.minosoft.config.profile.Boxed
import de.bixilon.minosoft.config.profile.delegate.types.RedirectDelegate
import de.bixilon.minosoft.config.profile.delegate.types.StringDelegate
import de.bixilon.minosoft.config.profile.profiles.Profile
class ConfigC(profile: Profile) {
@get:JsonDeserialize(using = RedirectDelegate.RedirectDeserializer::class)
var prop by RedirectDelegate<Boxed?, Int?>(profile, { it?.value }, { it?.let { Boxed(it, false) } })
var normal by StringDelegate(profile, "test")
}

View File

@ -13,11 +13,16 @@
package de.bixilon.minosoft.config.profile.delegate.types package de.bixilon.minosoft.config.profile.delegate.types
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import de.bixilon.kutil.observer.DataObserver import de.bixilon.kutil.observer.DataObserver
import de.bixilon.minosoft.config.profile.delegate.AbstractProfileDelegate import de.bixilon.minosoft.config.profile.delegate.AbstractProfileDelegate
import de.bixilon.minosoft.config.profile.profiles.Profile import de.bixilon.minosoft.config.profile.profiles.Profile
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@JsonDeserialize(using = RedirectDelegate.RedirectDeserializer::class)
class RedirectDelegate<V, S>( class RedirectDelegate<V, S>(
override val profile: Profile, override val profile: Profile,
val serializer: (V?) -> S?, val serializer: (V?) -> S?,
@ -33,4 +38,12 @@ class RedirectDelegate<V, S>(
// fun setValue(thisRef: Any, property: KProperty<*>, value: S?) { // fun setValue(thisRef: Any, property: KProperty<*>, value: S?) {
// setValue(thisRef, property, lookup(value)) // setValue(thisRef, property, lookup(value))
// } // }
object RedirectDeserializer : StdDeserializer<Any>(Any::class.java) {
override fun deserialize(parser: JsonParser, context: DeserializationContext?): Any {
return "test"
}
}
} }

View File

@ -146,7 +146,9 @@ abstract class StorageProfileManager<P : Profile> : Iterable<P>, Identified {
this.selected = this[selected] ?: create(selected) this.selected = this[selected] ?: create(selected)
this::selected.observe(this) { ProfileIOManager.saveSelected(this) } this::selected.observe(this) { ProfileIOManager.saveSelected(this) }
observe(root.toPath()) if (RunConfiguration.PROFILES_HOT_RELOADING) {
observe(root.toPath())
}
} }
private fun observe(root: Path) { private fun observe(root: Path) {