ScalaBot/scalabot-app/src/test/kotlin/util/UtilsKtTest.kt
LamGC 478480014a
perf(utils): 优化自动释放钩子的资源引用.
原本自动释放钩子对资源的引用, 可能会出现资源已经被关闭, 但仍然无法被 GC 回收的问题.
此次改动, 将会让钩子在关闭资源后, 将资源从列表中移除.
虽然, 自动释放钩子设计上仅会被 System.exit 动作触发, 但保险起见还是加上这个改动.
2022-05-05 16:52:29 +08:00

119 lines
4.4 KiB
Kotlin

package net.lamgc.scalabot.util
import io.mockk.every
import io.mockk.justRun
import io.mockk.mockk
import io.mockk.verify
import net.lamgc.scalabot.ExtensionPackageFinder
import net.lamgc.scalabot.FinderPriority
import net.lamgc.scalabot.FinderRules
import net.lamgc.scalabot.FoundExtensionPackage
import org.eclipse.aether.artifact.Artifact
import org.eclipse.aether.artifact.DefaultArtifact
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.assertThrows
import java.io.File
import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import kotlin.test.*
internal class UtilsKtTest {
@Test
fun `Extension Function - Artifact_equalsArtifact`() {
val equalGAV = "org.example:demo:1.0.0-SNAPSHOT"
assertTrue(DefaultArtifact(equalGAV).equalsArtifact(DefaultArtifact(equalGAV)))
assertFalse(
DefaultArtifact("org.example:demo:1.0.0")
.equalsArtifact(DefaultArtifact("com.example:demo-2:1.0.0-SNAPSHOT"))
)
}
@Test
fun `bytes to hex`() {
assertEquals("48656c6c6f20576f726c64", "Hello World".toByteArray(StandardCharsets.UTF_8).toHexString())
}
@Test
fun `ExtensionPackageFinder - getPriority`() {
open class BaseTestFinder : ExtensionPackageFinder {
override fun findByArtifact(extensionArtifact: Artifact, extensionsPath: File): Set<FoundExtensionPackage> {
throw IllegalStateException("Calling this class is not allowed.")
}
}
@FinderRules(FinderPriority.ALTERNATE)
class StandardTestFinder : BaseTestFinder()
assertEquals(
FinderPriority.ALTERNATE, StandardTestFinder().getPriority(),
"获取到的优先值与预期不符"
)
@FinderRules(-1)
class OutOfRangePriorityFinder : BaseTestFinder()
assertThrows<IllegalArgumentException>("getPriority 方法没有对超出范围的优先值抛出异常.") {
OutOfRangePriorityFinder().getPriority()
}
class NoAnnotationFinder : BaseTestFinder()
assertThrows<NoSuchFieldException> {
NoAnnotationFinder().getPriority()
}
}
@Test
fun `AutoCloseable shutdown hook`() {
val utilsInternalClass = Class.forName("net.lamgc.scalabot.util.UtilsInternal")
val utilsInternalObject = utilsInternalClass.getDeclaredField("INSTANCE").get(null)
?: fail("无法获取 UtilsInternal 对象.")
val doCloseResourcesMethod = utilsInternalClass.getDeclaredMethod("doCloseResources")
.apply {
isAccessible = true
}
// 正常的运行过程.
val mockResource = mockk<AutoCloseable> {
justRun { close() }
}.registerShutdownHook()
doCloseResourcesMethod.invoke(utilsInternalObject)
verify { mockResource.close() }
// 异常捕获检查.
val exceptionMockResource = mockk<AutoCloseable> {
every { close() } throws RuntimeException("Expected exception.")
}.registerShutdownHook()
assertDoesNotThrow("在关闭资源时出现未捕获异常.") {
doCloseResourcesMethod.invoke(utilsInternalObject)
}
verify { exceptionMockResource.close() }
// 错误抛出检查.
val errorMockResource = mockk<AutoCloseable> {
every { close() } throws Error("Expected error.")
}.registerShutdownHook()
assertThrows<Error>("关闭资源时捕获了不该捕获的 Error.") {
try {
doCloseResourcesMethod.invoke(utilsInternalObject)
} catch (e: InvocationTargetException) {
throw e.targetException
}
}
verify { errorMockResource.close() }
@Suppress("UNCHECKED_CAST")
val resourceSet = utilsInternalClass.getDeclaredMethod("getAutoCloseableSet").invoke(utilsInternalObject)
as MutableSet<AutoCloseable>
resourceSet.clear()
val closeRef = mockk<AutoCloseable> {
justRun { close() }
}
resourceSet.add(closeRef)
assertTrue(resourceSet.contains(closeRef), "测试用资源虚引用添加失败.")
doCloseResourcesMethod.invoke(utilsInternalObject)
assertFalse(resourceSet.contains(closeRef), "资源虚引用未从列表中删除.")
resourceSet.clear()
}
}