mirror of
https://github.com/LamGC/ScalaBot.git
synced 2025-04-29 22:27:31 +00:00
test(config): 补充相关的单元测试.
经检查, 已确定完全覆盖代码, 为完成单元测试的编写, 稍微改了一下 AppPaths 的代码, 不会有影响的 :P
This commit is contained in:
parent
8c4e48e3eb
commit
92b7e84b3a
@ -167,6 +167,21 @@ internal enum class AppPaths(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个内部方法, 用于将 [initialized] 状态重置.
|
||||
*
|
||||
* 如果不重置该状态, 将使得单元测试无法让 AppPath 重新初始化文件.
|
||||
*
|
||||
* 警告: 该方法不应该被非测试代码调用.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
private fun reset() {
|
||||
log.warn {
|
||||
"初始化状态已重置: `${this.name}`, 如果在非测试环境中重置状态, 请报告该问题."
|
||||
}
|
||||
initialized.set(false)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return path
|
||||
}
|
||||
|
@ -4,31 +4,38 @@ import com.github.stefanbirkner.systemlambda.SystemLambda
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mu.KotlinLogging
|
||||
import net.lamgc.scalabot.config.MavenRepositoryConfig
|
||||
import net.lamgc.scalabot.config.ProxyConfig
|
||||
import net.lamgc.scalabot.config.ProxyType
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
||||
import java.io.File
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import kotlin.test.*
|
||||
|
||||
internal class AppPathsTest {
|
||||
|
||||
@Test
|
||||
fun `Data root path priority`() {
|
||||
System.setProperty("bot.path.data", "fromSystemProperties")
|
||||
System.setProperty(AppPaths.PathConst.PROP_DATA_PATH, "fromSystemProperties")
|
||||
|
||||
assertEquals("fromSystemProperties", AppPaths.DATA_ROOT.file.path, "`DATA_ROOT`没有优先返回 Property 的值.")
|
||||
System.getProperties().remove("bot.path.data")
|
||||
System.getProperties().remove(AppPaths.PathConst.PROP_DATA_PATH)
|
||||
|
||||
val expectEnvValue = "fromEnvironmentVariable"
|
||||
SystemLambda.withEnvironmentVariable("BOT_DATA_PATH", expectEnvValue).execute {
|
||||
SystemLambda.withEnvironmentVariable(AppPaths.PathConst.ENV_DATA_PATH, expectEnvValue).execute {
|
||||
assertEquals(
|
||||
expectEnvValue, AppPaths.DATA_ROOT.file.path,
|
||||
"`DATA_ROOT`没有优先返回 env 的值."
|
||||
)
|
||||
}
|
||||
|
||||
SystemLambda.withEnvironmentVariable("BOT_DATA_PATH", null).execute {
|
||||
SystemLambda.withEnvironmentVariable(AppPaths.PathConst.ENV_DATA_PATH, null).execute {
|
||||
assertEquals(
|
||||
System.getProperty("user.dir"), AppPaths.DATA_ROOT.file.path,
|
||||
"`DATA_ROOT`没有返回 System.properties `user.dir` 的值."
|
||||
@ -116,5 +123,270 @@ internal class AppPathsTest {
|
||||
defaultInitializerMethod.isAccessible = false
|
||||
}
|
||||
|
||||
}
|
||||
@Test
|
||||
fun `loadBotConfig test`(@TempDir testDir: File) {
|
||||
assertNull(loadBotConfigJson(File("/NOT_EXISTS_FILE")), "加载 BotConfigs 失败时应该返回 null.")
|
||||
|
||||
SystemLambda.withEnvironmentVariable(AppPaths.PathConst.ENV_DATA_PATH, testDir.canonicalPath).execute {
|
||||
assertNull(loadBotConfigJson(), "加载 BotConfigs 失败时应该返回 null.")
|
||||
|
||||
File(testDir, "bot.json").apply {
|
||||
//language=JSON5
|
||||
writeText(
|
||||
"""
|
||||
[
|
||||
{
|
||||
"enabled": false,
|
||||
"account": {
|
||||
"name": "TestBot",
|
||||
"token": "123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||
"creatorId": 123456789
|
||||
},
|
||||
"proxy": {
|
||||
"host": "localhost",
|
||||
"port": 8080,
|
||||
"type": "HTTP"
|
||||
},
|
||||
"disableBuiltInAbility": false,
|
||||
"autoUpdateCommandList": true,
|
||||
"extensions": [
|
||||
"org.example.test:test-extension:1.0.0"
|
||||
],
|
||||
"baseApiUrl": "http://localhost:8080"
|
||||
}
|
||||
]
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
val botConfigJsons = loadBotConfigJson()
|
||||
assertNotNull(botConfigJsons)
|
||||
assertEquals(1, botConfigJsons.size())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `loadAppConfig test`(@TempDir testDir: File) {
|
||||
assertThrows<IOException>("加载失败时应该抛出 IOException.") {
|
||||
loadAppConfig(File("/NOT_EXISTS_FILE"))
|
||||
}
|
||||
|
||||
SystemLambda.withEnvironmentVariable(AppPaths.PathConst.ENV_DATA_PATH, testDir.canonicalPath).execute {
|
||||
assertThrows<IOException>("加载失败时应该抛出 IOException.") {
|
||||
loadAppConfig()
|
||||
}
|
||||
|
||||
File(testDir, "config.json").apply {
|
||||
//language=JSON5
|
||||
writeText(
|
||||
"""
|
||||
{
|
||||
"proxy": {
|
||||
"type": "HTTP",
|
||||
"host": "localhost",
|
||||
"port": 8080
|
||||
},
|
||||
"metrics": {
|
||||
"enable": true,
|
||||
"port": 8800,
|
||||
"bindAddress": "127.0.0.1",
|
||||
"authenticator": {
|
||||
"username": "username",
|
||||
"password": "password"
|
||||
}
|
||||
},
|
||||
"mavenRepositories": [
|
||||
{
|
||||
"url": "https://repository.maven.apache.org/maven2/"
|
||||
}
|
||||
],
|
||||
"mavenLocalRepository": "file:///tmp/maven-local-repository"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
val appConfigs = loadAppConfig()
|
||||
assertNotNull(appConfigs)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ProxyType_toTelegramBotsType test`() {
|
||||
val expectTypeMapping = mapOf(
|
||||
ProxyType.NO_PROXY to DefaultBotOptions.ProxyType.NO_PROXY,
|
||||
ProxyType.SOCKS5 to DefaultBotOptions.ProxyType.SOCKS5,
|
||||
ProxyType.SOCKS4 to DefaultBotOptions.ProxyType.SOCKS4,
|
||||
ProxyType.HTTP to DefaultBotOptions.ProxyType.HTTP,
|
||||
ProxyType.HTTPS to DefaultBotOptions.ProxyType.HTTP
|
||||
)
|
||||
|
||||
for (proxyType in ProxyType.values()) {
|
||||
assertEquals(
|
||||
expectTypeMapping[proxyType],
|
||||
proxyType.toTelegramBotsType(),
|
||||
"ProxyType 转换失败."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ProxyConfig_toAetherProxy test`() {
|
||||
val host = "proxy.example.org"
|
||||
val port = 1080
|
||||
|
||||
val expectNotNullProxyType = setOf(
|
||||
ProxyType.HTTP,
|
||||
ProxyType.HTTPS
|
||||
)
|
||||
for (proxyType in ProxyType.values()) {
|
||||
val proxyConfig = ProxyConfig(proxyType, host, port)
|
||||
val aetherProxy = proxyConfig.toAetherProxy()
|
||||
if (expectNotNullProxyType.contains(proxyType)) {
|
||||
assertNotNull(aetherProxy, "支持的代理类型应该不为 null.")
|
||||
assertEquals(host, aetherProxy.host)
|
||||
assertEquals(port, aetherProxy.port)
|
||||
} else {
|
||||
assertNull(aetherProxy, "不支持的代理类型应该返回 null.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `MavenRepositoryConfig_toRemoteRepository test`() {
|
||||
val defaultMavenRepositoryConfig = MavenRepositoryConfig(
|
||||
url = URL(MavenRepositoryExtensionFinder.MAVEN_CENTRAL_URL),
|
||||
enableReleases = true,
|
||||
enableSnapshots = false
|
||||
)
|
||||
val remoteRepositoryWithoutId = defaultMavenRepositoryConfig.toRemoteRepository(
|
||||
ProxyConfig(ProxyType.NO_PROXY, "", 0)
|
||||
)
|
||||
assertEquals(MavenRepositoryExtensionFinder.MAVEN_CENTRAL_URL, remoteRepositoryWithoutId.url.toString())
|
||||
assertNotNull(remoteRepositoryWithoutId.id)
|
||||
assertTrue(remoteRepositoryWithoutId.getPolicy(false).isEnabled)
|
||||
assertFalse(remoteRepositoryWithoutId.getPolicy(true).isEnabled)
|
||||
|
||||
val remoteRepositoryWithId = defaultMavenRepositoryConfig.copy(id = "test-repo").toRemoteRepository(
|
||||
ProxyConfig(ProxyType.HTTP, "127.0.0.1", 1080)
|
||||
)
|
||||
|
||||
assertEquals("test-repo", remoteRepositoryWithId.id)
|
||||
assertEquals(MavenRepositoryExtensionFinder.MAVEN_CENTRAL_URL, remoteRepositoryWithId.url.toString())
|
||||
assertEquals("http", remoteRepositoryWithId.proxy.type)
|
||||
assertEquals("127.0.0.1", remoteRepositoryWithId.proxy.host)
|
||||
assertEquals(1080, remoteRepositoryWithId.proxy.port)
|
||||
assertEquals(remoteRepositoryWithId.id, remoteRepositoryWithId.id)
|
||||
|
||||
val remoteRepositoryWithProxy = defaultMavenRepositoryConfig.copy(
|
||||
id = "test-repo",
|
||||
proxy = ProxyConfig(ProxyType.HTTP, "example.org", 1080).toAetherProxy()
|
||||
).toRemoteRepository(ProxyConfig(ProxyType.HTTP, "localhost", 8080))
|
||||
assertEquals("http", remoteRepositoryWithProxy.proxy.type)
|
||||
assertEquals("example.org", remoteRepositoryWithProxy.proxy.host, "未优先使用 MavenRepositoryConfig 中的 proxy 属性.")
|
||||
assertEquals(1080, remoteRepositoryWithProxy.proxy.port, "未优先使用 MavenRepositoryConfig 中的 proxy 属性.")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkRepositoryLayout test`() {
|
||||
val noProxyConfig = ProxyConfig(ProxyType.NO_PROXY, "", 0)
|
||||
assertEquals(
|
||||
"default", MavenRepositoryConfig(url = URL("https://repo.example.org"))
|
||||
.toRemoteRepository(noProxyConfig).contentType
|
||||
)
|
||||
assertEquals(
|
||||
"legacy", MavenRepositoryConfig(url = URL("https://repo.example.org"), layout = "LEgaCY")
|
||||
.toRemoteRepository(noProxyConfig).contentType
|
||||
)
|
||||
assertThrows<IllegalArgumentException> {
|
||||
MavenRepositoryConfig(
|
||||
url = URL("https://repo.example.org"),
|
||||
layout = "NOT_EXISTS_LAYOUT"
|
||||
).toRemoteRepository(noProxyConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initialFiles test`(@TempDir testDir: Path) {
|
||||
// 这么做是为了让日志文件创建在其他地方, 由于日志文件在运行时会持续占用, 在 windows 中文件会被锁定,
|
||||
// 导致测试框架无法正常清除测试所使用的临时文件夹.
|
||||
val logsDir = Files.createTempDirectory("ammmmmm-logs-")
|
||||
System.setProperty(AppPaths.PathConst.PROP_DATA_PATH, logsDir.toString())
|
||||
assertEquals(logsDir.toString(), AppPaths.DATA_ROOT.path, "日志目录设定失败.")
|
||||
KotlinLogging.logger("TEST").error { "日志占用.(无需理会), 日志目录: $logsDir" }
|
||||
AppPaths.DATA_LOGS.file.listFiles { _, name -> name.endsWith(".log") }?.forEach {
|
||||
it.deleteOnExit()
|
||||
}
|
||||
|
||||
val fullInitializeDir = Files.createTempDirectory(testDir, "fullInitialize")
|
||||
System.setProperty(AppPaths.PathConst.PROP_DATA_PATH, fullInitializeDir.toString())
|
||||
assertEquals(fullInitializeDir.toString(), AppPaths.DATA_ROOT.path, "测试路径设定失败.")
|
||||
|
||||
assertTrue(initialFiles(), "方法未能提醒用户编辑初始配置文件.")
|
||||
|
||||
for (path in AppPaths.values()) {
|
||||
assertTrue(path.file.exists(), "文件未初始化成功: ${path.path}")
|
||||
if (path.file.isFile) {
|
||||
assertNotEquals(0, path.file.length(), "文件未初始化成功(大小为 0): ${path.path}")
|
||||
}
|
||||
path.reset()
|
||||
}
|
||||
|
||||
assertFalse(initialFiles(), "方法试图在配置已初始化的情况下提醒用户编辑初始配置文件.")
|
||||
|
||||
for (path in AppPaths.values()) {
|
||||
assertTrue(path.file.exists(), "文件未初始化成功: ${path.path}")
|
||||
if (path.file.isFile) {
|
||||
assertNotEquals(0, path.file.length(), "文件未初始化成功(大小为 0): ${path.path}")
|
||||
}
|
||||
path.reset()
|
||||
}
|
||||
|
||||
assertTrue(AppPaths.CONFIG_APPLICATION.file.delete(), "config.json 删除失败.")
|
||||
assertFalse(initialFiles(), "方法试图在部分配置已初始化的情况下提醒用户编辑初始配置文件.")
|
||||
|
||||
for (path in AppPaths.values()) {
|
||||
assertTrue(path.file.exists(), "文件未初始化成功: ${path.path}")
|
||||
if (path.file.isFile) {
|
||||
assertNotEquals(0, path.file.length(), "文件未初始化成功(大小为 0): ${path.path}")
|
||||
}
|
||||
path.reset()
|
||||
}
|
||||
|
||||
assertTrue(AppPaths.CONFIG_BOT.file.delete(), "bot.json 删除失败.")
|
||||
assertFalse(initialFiles(), "方法试图在部分配置已初始化的情况下提醒用户编辑初始配置文件.")
|
||||
|
||||
for (path in AppPaths.values()) {
|
||||
assertTrue(path.file.exists(), "文件未初始化成功: ${path.path}")
|
||||
if (path.file.isFile) {
|
||||
assertNotEquals(0, path.file.length(), "文件未初始化成功(大小为 0): ${path.path}")
|
||||
}
|
||||
path.reset()
|
||||
}
|
||||
|
||||
assertTrue(AppPaths.CONFIG_APPLICATION.file.delete(), "config.json 删除失败.")
|
||||
assertTrue(AppPaths.CONFIG_BOT.file.delete(), "bot.json 删除失败.")
|
||||
assertTrue(
|
||||
initialFiles(),
|
||||
"在主要配置文件(config.json 和 bot.json)不存在的情况下初始化文件后, 方法未能提醒用户编辑初始配置文件."
|
||||
)
|
||||
|
||||
for (path in AppPaths.values()) {
|
||||
assertTrue(path.file.exists(), "文件未初始化成功: ${path.path}")
|
||||
if (path.file.isFile) {
|
||||
assertNotEquals(0, path.file.length(), "文件未初始化成功(大小为 0): ${path.path}")
|
||||
}
|
||||
path.reset()
|
||||
}
|
||||
|
||||
System.getProperties().remove(AppPaths.PathConst.PROP_DATA_PATH)
|
||||
}
|
||||
|
||||
private fun AppPaths.reset() {
|
||||
val method = AppPaths::class.java.getDeclaredMethod("reset")
|
||||
method.isAccessible = true
|
||||
method.invoke(this)
|
||||
method.isAccessible = false
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user