mirror of
https://github.com/LamGC/ScalaBot.git
synced 2025-04-30 06:37:29 +00:00
feat(meta): 新增 meta 模块.
将与配置相关的内容迁移到 scalabot-meta 模块. 其他项目可以使用 meta 模块来生成 ScalaBot 的配置文件, 通过配置文件管理 ScalaBot 的运行. BREAKING CHANGE: 与配置有关的类迁移到了 scalabot-meta 模块. 目前仅所有配置类 (以 `Config` 结尾的 Class) 和相应的序列化类 (以 `Serializer` 结尾的) 都迁移到了 meta 模块, 但其工具方法则作为扩展函数保留在 app 模块中. 这么做的好处是为了方便其他应用 (例如 ScalaBot 外部管理程序) 根据需要生成配置文件. scalabot-meta 将会作为依赖项发布, 可根据需要获取 ScalaBot-meta 生成 ScalaBot 的配置. + 此次改动普通用户无需迁移。
This commit is contained in:
commit
099c452fe7
@ -7,6 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(project(":scalabot-meta"))
|
||||||
implementation(project(":scalabot-extension"))
|
implementation(project(":scalabot-extension"))
|
||||||
|
|
||||||
implementation("org.slf4j:slf4j-api:1.7.36")
|
implementation("org.slf4j:slf4j-api:1.7.36")
|
||||||
|
@ -5,14 +5,14 @@ import com.google.gson.Gson
|
|||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import net.lamgc.scalabot.util.*
|
import net.lamgc.scalabot.config.*
|
||||||
|
import net.lamgc.scalabot.config.serializer.*
|
||||||
import org.eclipse.aether.artifact.Artifact
|
import org.eclipse.aether.artifact.Artifact
|
||||||
import org.eclipse.aether.repository.Authentication
|
import org.eclipse.aether.repository.Authentication
|
||||||
import org.eclipse.aether.repository.Proxy
|
import org.eclipse.aether.repository.Proxy
|
||||||
import org.eclipse.aether.repository.RemoteRepository
|
import org.eclipse.aether.repository.RemoteRepository
|
||||||
import org.eclipse.aether.repository.RepositoryPolicy
|
import org.eclipse.aether.repository.RepositoryPolicy
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
import org.telegram.telegrambots.bots.DefaultBotOptions
|
||||||
import org.telegram.telegrambots.meta.ApiConstants
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
@ -22,154 +22,65 @@ import kotlin.system.exitProcess
|
|||||||
|
|
||||||
private val log = KotlinLogging.logger { }
|
private val log = KotlinLogging.logger { }
|
||||||
|
|
||||||
/**
|
internal fun ProxyType.toTelegramBotsType(): DefaultBotOptions.ProxyType {
|
||||||
* 机器人帐号信息.
|
return when (this) {
|
||||||
* @property name 机器人名称, 建议与实际设定的名称相同.
|
ProxyType.NO_PROXY -> DefaultBotOptions.ProxyType.NO_PROXY
|
||||||
* @property token 机器人 API Token.
|
ProxyType.HTTP -> DefaultBotOptions.ProxyType.HTTP
|
||||||
* @property creatorId 机器人创建者, 管理机器人需要使用该信息.
|
ProxyType.HTTPS -> DefaultBotOptions.ProxyType.HTTP
|
||||||
*/
|
ProxyType.SOCKS4 -> DefaultBotOptions.ProxyType.SOCKS4
|
||||||
internal data class BotAccount(
|
ProxyType.SOCKS5 -> DefaultBotOptions.ProxyType.SOCKS5
|
||||||
val name: String,
|
}
|
||||||
val token: String,
|
|
||||||
val creatorId: Long = -1
|
|
||||||
) {
|
|
||||||
|
|
||||||
val id
|
|
||||||
// 不要想着每次获取都要从 token 里取出有性能损耗.
|
|
||||||
// 由于 Gson 解析方式, 如果不这么做, 会出现 token 设置前 id 初始化完成, 就只有"0"了,
|
|
||||||
// 虽然能过单元测试, 但实际使用过程是不能正常用的.
|
|
||||||
get() = token.substringBefore(":").toLong()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
internal fun ProxyConfig.toAetherProxy(): Proxy? {
|
||||||
* 机器人配置.
|
val typeStr = when (type) {
|
||||||
* @property account 机器人帐号信息, 用于访问 API.
|
ProxyType.HTTP -> Proxy.TYPE_HTTP
|
||||||
* @property disableBuiltInAbility 是否禁用 AbilityBot 自带命令.
|
ProxyType.HTTPS -> Proxy.TYPE_HTTPS
|
||||||
* @property extensions 该机器人启用的扩展.
|
else -> return null
|
||||||
* @property proxy 为该机器人单独设置的代理配置, 如无设置, 则使用 AppConfig 中的代理配置.
|
}
|
||||||
*/
|
return Proxy(typeStr, host, port)
|
||||||
internal data class BotConfig(
|
}
|
||||||
val enabled: Boolean = true,
|
|
||||||
val account: BotAccount,
|
|
||||||
val disableBuiltInAbility: Boolean = false,
|
|
||||||
val autoUpdateCommandList: Boolean = false,
|
|
||||||
/*
|
|
||||||
* 使用构件坐标来选择机器人所使用的扩展包.
|
|
||||||
* 这么做的原因是我暂时没找到一个合适的方法来让开发者方便地设定自己的扩展 Id,
|
|
||||||
* 而构件坐标(POM Reference 或者叫 GAV 坐标)是开发者创建 Maven/Gradle 项目时一定会设置的,
|
|
||||||
* 所以就直接用了. :P
|
|
||||||
*/
|
|
||||||
val extensions: Set<Artifact>,
|
|
||||||
val proxy: ProxyConfig? = ProxyConfig(),
|
|
||||||
val baseApiUrl: String? = ApiConstants.BASE_URL
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
internal fun MavenRepositoryConfig.toRemoteRepository(proxyConfig: ProxyConfig): RemoteRepository {
|
||||||
* 代理配置.
|
val builder =
|
||||||
* @property type 代理类型.
|
RemoteRepository.Builder(id ?: createDefaultRepositoryId(), checkRepositoryLayout(layout), url.toString())
|
||||||
* @property host 代理服务端地址.
|
if (proxy != null) {
|
||||||
* @property port 代理服务端端口.
|
builder.setProxy(proxy)
|
||||||
*/
|
} else if (proxyConfig.type == ProxyType.HTTP) {
|
||||||
internal data class ProxyConfig(
|
builder.setProxy(proxyConfig.toAetherProxy())
|
||||||
val type: DefaultBotOptions.ProxyType = DefaultBotOptions.ProxyType.NO_PROXY,
|
|
||||||
val host: String = "127.0.0.1",
|
|
||||||
val port: Int = 1080
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun toAetherProxy(): Proxy? {
|
|
||||||
return if (type == DefaultBotOptions.ProxyType.HTTP) {
|
|
||||||
Proxy(Proxy.TYPE_HTTP, host, port)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
builder.setReleasePolicy(
|
||||||
|
RepositoryPolicy(
|
||||||
internal data class MetricsConfig(
|
enableReleases,
|
||||||
val enable: Boolean = false,
|
RepositoryPolicy.UPDATE_POLICY_NEVER,
|
||||||
val port: Int = 9386,
|
RepositoryPolicy.CHECKSUM_POLICY_FAIL
|
||||||
val bindAddress: String? = "0.0.0.0",
|
|
||||||
val authenticator: UsernameAuthenticator? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maven 远端仓库配置.
|
|
||||||
* @property url 仓库地址.
|
|
||||||
* @property proxy 访问仓库所使用的代理, 仅支持 http/https 代理.
|
|
||||||
* @property layout 仓库布局版本, Maven 2 及以上使用 `default`, Maven 1 使用 `legacy`.
|
|
||||||
*/
|
|
||||||
internal data class MavenRepositoryConfig(
|
|
||||||
val id: String? = null,
|
|
||||||
val url: URL,
|
|
||||||
val proxy: Proxy? = null,
|
|
||||||
val layout: String = "default",
|
|
||||||
val enableReleases: Boolean = true,
|
|
||||||
val enableSnapshots: Boolean = true,
|
|
||||||
// 可能要设计个 type 来判断解析成什么类型的 Authentication.
|
|
||||||
val authentication: Authentication? = null
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun toRemoteRepository(proxyConfig: ProxyConfig): RemoteRepository {
|
|
||||||
val builder =
|
|
||||||
RemoteRepository.Builder(id ?: createDefaultRepositoryId(), checkRepositoryLayout(layout), url.toString())
|
|
||||||
if (proxy != null) {
|
|
||||||
builder.setProxy(proxy)
|
|
||||||
} else if (proxyConfig.type == DefaultBotOptions.ProxyType.HTTP) {
|
|
||||||
builder.setProxy(proxyConfig.toAetherProxy())
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setReleasePolicy(
|
|
||||||
RepositoryPolicy(
|
|
||||||
enableReleases,
|
|
||||||
RepositoryPolicy.UPDATE_POLICY_NEVER,
|
|
||||||
RepositoryPolicy.CHECKSUM_POLICY_FAIL
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
builder.setSnapshotPolicy(
|
)
|
||||||
RepositoryPolicy(
|
builder.setSnapshotPolicy(
|
||||||
enableSnapshots,
|
RepositoryPolicy(
|
||||||
RepositoryPolicy.UPDATE_POLICY_ALWAYS,
|
enableSnapshots,
|
||||||
RepositoryPolicy.CHECKSUM_POLICY_WARN
|
RepositoryPolicy.UPDATE_POLICY_ALWAYS,
|
||||||
)
|
RepositoryPolicy.CHECKSUM_POLICY_WARN
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
fun checkRepositoryLayout(layoutType: String): String {
|
|
||||||
val type = layoutType.trim().lowercase()
|
|
||||||
if (type != "default" && type != "legacy") {
|
|
||||||
throw IllegalArgumentException("Invalid layout type (expecting 'default' or 'legacy')")
|
|
||||||
}
|
|
||||||
return type
|
|
||||||
}
|
|
||||||
|
|
||||||
private val repoNumber = AtomicInteger(1)
|
|
||||||
|
|
||||||
fun createDefaultRepositoryId(): String {
|
|
||||||
return "Repository-${repoNumber.getAndIncrement()}"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun checkRepositoryLayout(layoutType: String): String {
|
||||||
* ScalaBot App 配置.
|
val type = layoutType.trim().lowercase()
|
||||||
*
|
if (type != "default" && type != "legacy") {
|
||||||
* App 配置信息与 BotConfig 分开, 分别存储在各自单独的文件中.
|
throw IllegalArgumentException("Invalid layout type (expecting 'default' or 'legacy')")
|
||||||
* @property proxy Telegram API 代理配置.
|
}
|
||||||
* @property metrics 运行指标数据配置. 可通过时序数据库记录运行数据.
|
return type
|
||||||
* @property mavenRepositories Maven 远端仓库配置.
|
}
|
||||||
* @property mavenLocalRepository Maven 本地仓库路径. 相对于运行目录 (而不是 DATA_ROOT 目录)
|
|
||||||
*/
|
private val repoNumberGenerator = AtomicInteger(1)
|
||||||
internal data class AppConfig(
|
|
||||||
val proxy: ProxyConfig = ProxyConfig(),
|
private fun createDefaultRepositoryId(): String {
|
||||||
val metrics: MetricsConfig = MetricsConfig(),
|
return "Repository-${repoNumberGenerator.getAndIncrement()}"
|
||||||
val mavenRepositories: List<MavenRepositoryConfig> = emptyList(),
|
}
|
||||||
val mavenLocalRepository: String? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 需要用到的路径.
|
* 需要用到的路径.
|
||||||
@ -222,7 +133,7 @@ internal enum class AppPaths(
|
|||||||
GsonConst.botConfigGson.toJson(
|
GsonConst.botConfigGson.toJson(
|
||||||
setOf(
|
setOf(
|
||||||
BotConfig(
|
BotConfig(
|
||||||
enabled = false,
|
enabled = true,
|
||||||
proxy = ProxyConfig(),
|
proxy = ProxyConfig(),
|
||||||
account = BotAccount(
|
account = BotAccount(
|
||||||
"Bot Username",
|
"Bot Username",
|
||||||
@ -317,14 +228,15 @@ private object GsonConst {
|
|||||||
.create()
|
.create()
|
||||||
|
|
||||||
val appConfigGson: Gson = baseGson.newBuilder()
|
val appConfigGson: Gson = baseGson.newBuilder()
|
||||||
.registerTypeAdapter(DefaultBotOptions.ProxyType::class.java, ProxyTypeSerializer)
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
.registerTypeAdapter(MavenRepositoryConfig::class.java, MavenRepositoryConfigSerializer)
|
.registerTypeAdapter(MavenRepositoryConfig::class.java, MavenRepositoryConfigSerializer)
|
||||||
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
||||||
.registerTypeAdapter(UsernameAuthenticator::class.java, UsernameAuthenticatorSerializer)
|
.registerTypeAdapter(UsernameAuthenticator::class.java, UsernameAuthenticatorSerializer)
|
||||||
.create()
|
.create()
|
||||||
|
|
||||||
val botConfigGson: Gson = baseGson.newBuilder()
|
val botConfigGson: Gson = baseGson.newBuilder()
|
||||||
.registerTypeAdapter(DefaultBotOptions.ProxyType::class.java, ProxyTypeSerializer)
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
|
.registerTypeAdapter(BotConfig::class.java, BotConfigSerializer)
|
||||||
.registerTypeAdapter(Artifact::class.java, ArtifactSerializer)
|
.registerTypeAdapter(Artifact::class.java, ArtifactSerializer)
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,10 @@ package net.lamgc.scalabot
|
|||||||
import io.prometheus.client.exporter.HTTPServer
|
import io.prometheus.client.exporter.HTTPServer
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
import net.lamgc.scalabot.config.AppConfig
|
||||||
|
import net.lamgc.scalabot.config.BotConfig
|
||||||
|
import net.lamgc.scalabot.config.MetricsConfig
|
||||||
|
import net.lamgc.scalabot.config.ProxyType
|
||||||
import net.lamgc.scalabot.util.registerShutdownHook
|
import net.lamgc.scalabot.util.registerShutdownHook
|
||||||
import org.eclipse.aether.repository.LocalRepository
|
import org.eclipse.aether.repository.LocalRepository
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
import org.telegram.telegrambots.bots.DefaultBotOptions
|
||||||
@ -71,9 +75,9 @@ internal class Launcher(private val config: AppConfig = Const.config) : AutoClos
|
|||||||
|
|
||||||
private fun getMavenLocalRepository(): LocalRepository {
|
private fun getMavenLocalRepository(): LocalRepository {
|
||||||
val localPath =
|
val localPath =
|
||||||
if (config.mavenLocalRepository != null && config.mavenLocalRepository.isNotEmpty()) {
|
if (config.mavenLocalRepository != null && config.mavenLocalRepository!!.isNotEmpty()) {
|
||||||
val repoPath = AppPaths.DATA_ROOT.file.toPath()
|
val repoPath = AppPaths.DATA_ROOT.file.toPath()
|
||||||
.resolve(config.mavenLocalRepository)
|
.resolve(config.mavenLocalRepository!!)
|
||||||
.apply {
|
.apply {
|
||||||
if (!exists()) {
|
if (!exists()) {
|
||||||
if (!parent.isWritable() || !parent.isReadable()) {
|
if (!parent.isWritable() || !parent.isReadable()) {
|
||||||
@ -133,23 +137,21 @@ internal class Launcher(private val config: AppConfig = Const.config) : AutoClos
|
|||||||
log.info { "正在启动机器人 `${botConfig.account.name}`..." }
|
log.info { "正在启动机器人 `${botConfig.account.name}`..." }
|
||||||
val botOption = DefaultBotOptions().apply {
|
val botOption = DefaultBotOptions().apply {
|
||||||
val proxyConfig =
|
val proxyConfig =
|
||||||
if (botConfig.proxy != null && botConfig.proxy.type != DefaultBotOptions.ProxyType.NO_PROXY) {
|
if (botConfig.proxy.type != ProxyType.NO_PROXY) {
|
||||||
botConfig.proxy
|
botConfig.proxy
|
||||||
} else if (config.proxy.type != DefaultBotOptions.ProxyType.NO_PROXY) {
|
} else if (config.proxy.type != ProxyType.NO_PROXY) {
|
||||||
config.proxy
|
config.proxy
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
if (proxyConfig != null) {
|
if (proxyConfig != null) {
|
||||||
proxyType = proxyConfig.type
|
proxyType = proxyConfig.type.toTelegramBotsType()
|
||||||
proxyHost = config.proxy.host
|
proxyHost = config.proxy.host
|
||||||
proxyPort = config.proxy.port
|
proxyPort = config.proxy.port
|
||||||
log.debug { "机器人 `${botConfig.account.name}` 已启用代理配置: $proxyConfig" }
|
log.debug { "机器人 `${botConfig.account.name}` 已启用代理配置: $proxyConfig" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (botConfig.baseApiUrl != null) {
|
baseUrl = botConfig.baseApiUrl
|
||||||
baseUrl = botConfig.baseApiUrl
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val account = botConfig.account
|
val account = botConfig.account
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package net.lamgc.scalabot
|
|||||||
|
|
||||||
import com.google.common.io.Files
|
import com.google.common.io.Files
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
import net.lamgc.scalabot.config.BotAccount
|
||||||
import net.lamgc.scalabot.util.toHexString
|
import net.lamgc.scalabot.util.toHexString
|
||||||
import org.mapdb.DB
|
import org.mapdb.DB
|
||||||
import org.mapdb.DBException
|
import org.mapdb.DBException
|
||||||
|
@ -4,6 +4,7 @@ import io.prometheus.client.Counter
|
|||||||
import io.prometheus.client.Gauge
|
import io.prometheus.client.Gauge
|
||||||
import io.prometheus.client.Summary
|
import io.prometheus.client.Summary
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
import net.lamgc.scalabot.config.BotConfig
|
||||||
import org.eclipse.aether.artifact.Artifact
|
import org.eclipse.aether.artifact.Artifact
|
||||||
import org.telegram.abilitybots.api.bot.AbilityBot
|
import org.telegram.abilitybots.api.bot.AbilityBot
|
||||||
import org.telegram.abilitybots.api.db.DBContext
|
import org.telegram.abilitybots.api.db.DBContext
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
package net.lamgc.scalabot.util
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import net.lamgc.scalabot.MavenRepositoryConfig
|
|
||||||
import org.eclipse.aether.artifact.Artifact
|
|
||||||
import org.eclipse.aether.artifact.DefaultArtifact
|
|
||||||
import org.eclipse.aether.repository.Authentication
|
|
||||||
import org.eclipse.aether.repository.Proxy
|
|
||||||
import org.eclipse.aether.util.repository.AuthenticationBuilder
|
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
internal object ProxyTypeSerializer : JsonDeserializer<DefaultBotOptions.ProxyType>,
|
|
||||||
JsonSerializer<DefaultBotOptions.ProxyType> {
|
|
||||||
|
|
||||||
override fun deserialize(
|
|
||||||
json: JsonElement,
|
|
||||||
typeOfT: Type?,
|
|
||||||
context: JsonDeserializationContext?
|
|
||||||
): DefaultBotOptions.ProxyType {
|
|
||||||
if (json.isJsonNull) {
|
|
||||||
return DefaultBotOptions.ProxyType.NO_PROXY
|
|
||||||
}
|
|
||||||
if (!json.isJsonPrimitive) {
|
|
||||||
throw JsonParseException("Wrong configuration value type.")
|
|
||||||
}
|
|
||||||
val value = json.asString.trim()
|
|
||||||
try {
|
|
||||||
return DefaultBotOptions.ProxyType.valueOf(value.uppercase())
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
throw JsonParseException("Invalid value: $value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(
|
|
||||||
src: DefaultBotOptions.ProxyType,
|
|
||||||
typeOfSrc: Type?,
|
|
||||||
context: JsonSerializationContext?
|
|
||||||
): JsonElement {
|
|
||||||
return JsonPrimitive(src.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object ArtifactSerializer : JsonSerializer<Artifact>, JsonDeserializer<Artifact> {
|
|
||||||
override fun serialize(src: Artifact, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
|
|
||||||
val gavBuilder = StringBuilder("${src.groupId}:${src.artifactId}")
|
|
||||||
if (!src.extension.equals("jar")) {
|
|
||||||
gavBuilder.append(':').append(src.extension)
|
|
||||||
}
|
|
||||||
if (src.classifier.isNotEmpty()) {
|
|
||||||
gavBuilder.append(':').append(src.classifier)
|
|
||||||
}
|
|
||||||
return JsonPrimitive(gavBuilder.append(':').append(src.version).toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Artifact {
|
|
||||||
if (!json.isJsonPrimitive) {
|
|
||||||
throw JsonParseException("Wrong configuration value type.")
|
|
||||||
}
|
|
||||||
return DefaultArtifact(json.asString.trim())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object AuthenticationSerializer : JsonDeserializer<Authentication> {
|
|
||||||
|
|
||||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Authentication {
|
|
||||||
if (json !is JsonObject) {
|
|
||||||
throw JsonParseException("Unsupported JSON type.")
|
|
||||||
}
|
|
||||||
val username = SerializerUtils.checkJsonKey(json, "username")
|
|
||||||
val password = SerializerUtils.checkJsonKey(json, "password")
|
|
||||||
val builder = AuthenticationBuilder()
|
|
||||||
builder.addUsername(username)
|
|
||||||
builder.addPassword(password)
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private object SerializerUtils {
|
|
||||||
fun checkJsonKey(json: JsonObject, key: String): String {
|
|
||||||
if (!json.has(key)) {
|
|
||||||
throw JsonParseException("Required field does not exist: $key")
|
|
||||||
} else if (!json.get(key).isJsonPrimitive) {
|
|
||||||
throw JsonParseException("Wrong field `$key` type: ${json.get(key)::class.java}")
|
|
||||||
}
|
|
||||||
return json.get(key).asString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object MavenRepositoryConfigSerializer
|
|
||||||
: JsonDeserializer<MavenRepositoryConfig> {
|
|
||||||
|
|
||||||
override fun deserialize(
|
|
||||||
json: JsonElement,
|
|
||||||
typeOfT: Type,
|
|
||||||
context: JsonDeserializationContext
|
|
||||||
): MavenRepositoryConfig {
|
|
||||||
return when (json) {
|
|
||||||
is JsonObject -> {
|
|
||||||
MavenRepositoryConfig(
|
|
||||||
id = json.get("id")?.asString,
|
|
||||||
url = URL(SerializerUtils.checkJsonKey(json, "url")),
|
|
||||||
proxy = if (json.has("proxy") && json.get("proxy").isJsonObject)
|
|
||||||
context.deserialize<Proxy>(
|
|
||||||
json.getAsJsonObject("proxy"), Proxy::class.java
|
|
||||||
) else null,
|
|
||||||
layout = json.get("layout")?.asString ?: "default",
|
|
||||||
enableReleases = json.get("enableReleases")?.asBoolean ?: true,
|
|
||||||
enableSnapshots = json.get("enableSnapshots")?.asBoolean ?: true,
|
|
||||||
authentication = if (json.has("authentication") && json.get("authentication").isJsonObject)
|
|
||||||
context.deserialize<Authentication>(
|
|
||||||
json.getAsJsonObject("authentication"), Authentication::class.java
|
|
||||||
) else null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is JsonPrimitive -> {
|
|
||||||
MavenRepositoryConfig(url = URL(json.asString))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
throw JsonParseException("Unsupported Maven warehouse configuration type.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package net.lamgc.scalabot.util
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import com.sun.net.httpserver.BasicAuthenticator
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
|
|
||||||
class UsernameAuthenticator(private val username: String, private val password: String) :
|
|
||||||
BasicAuthenticator("metrics") {
|
|
||||||
override fun checkCredentials(username: String?, password: String?): Boolean =
|
|
||||||
this.username == username && this.password == password
|
|
||||||
|
|
||||||
fun toJsonObject(): JsonObject = JsonObject().apply {
|
|
||||||
addProperty("username", username)
|
|
||||||
addProperty("password", password)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
return other is UsernameAuthenticator && this.username == other.username && this.password == other.password
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = username.hashCode()
|
|
||||||
result = 31 * result + password.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object UsernameAuthenticatorSerializer : JsonSerializer<UsernameAuthenticator>,
|
|
||||||
JsonDeserializer<UsernameAuthenticator> {
|
|
||||||
|
|
||||||
override fun serialize(
|
|
||||||
src: UsernameAuthenticator,
|
|
||||||
typeOfSrc: Type?,
|
|
||||||
context: JsonSerializationContext?
|
|
||||||
): JsonElement {
|
|
||||||
return src.toJsonObject()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(
|
|
||||||
json: JsonElement,
|
|
||||||
typeOfT: Type?,
|
|
||||||
context: JsonDeserializationContext?
|
|
||||||
): UsernameAuthenticator? {
|
|
||||||
if (json.isJsonNull) {
|
|
||||||
return null
|
|
||||||
} else if (!json.isJsonObject) {
|
|
||||||
throw JsonParseException("Invalid attribute value type.")
|
|
||||||
}
|
|
||||||
|
|
||||||
val jsonObj = json.asJsonObject
|
|
||||||
|
|
||||||
if (jsonObj["username"]?.isJsonPrimitive != true) {
|
|
||||||
throw JsonParseException("Invalid attribute value: username")
|
|
||||||
} else if (jsonObj["password"]?.isJsonPrimitive != true) {
|
|
||||||
throw JsonParseException("Invalid attribute value: password")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jsonObj["username"].asString.isEmpty() || jsonObj["password"].asString.isEmpty()) {
|
|
||||||
throw JsonParseException("`username` or `password` is empty.")
|
|
||||||
}
|
|
||||||
return UsernameAuthenticator(jsonObj["username"].asString, jsonObj["password"].asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +1,16 @@
|
|||||||
package net.lamgc.scalabot
|
package net.lamgc.scalabot
|
||||||
|
|
||||||
import com.github.stefanbirkner.systemlambda.SystemLambda
|
import com.github.stefanbirkner.systemlambda.SystemLambda
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import org.junit.jupiter.api.io.TempDir
|
import org.junit.jupiter.api.io.TempDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
internal class BotAccountTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `id getter`() {
|
|
||||||
val accountId = abs(Random().nextInt()).toLong()
|
|
||||||
assertEquals(accountId, BotAccount("Test", "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", 0).id)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deserializerTest() {
|
|
||||||
val accountId = abs(Random().nextInt()).toLong()
|
|
||||||
val creatorId = abs(Random().nextInt()).toLong()
|
|
||||||
val botAccountJsonObject = Gson().fromJson(
|
|
||||||
"""
|
|
||||||
{
|
|
||||||
"name": "TestBot",
|
|
||||||
"token": "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
|
||||||
"creatorId": $creatorId
|
|
||||||
}
|
|
||||||
""".trimIndent(), JsonObject::class.java
|
|
||||||
)
|
|
||||||
val botAccount = Gson().fromJson(botAccountJsonObject, BotAccount::class.java)
|
|
||||||
assertEquals(botAccountJsonObject["name"].asString, botAccount.name)
|
|
||||||
assertEquals(botAccountJsonObject["token"].asString, botAccount.token)
|
|
||||||
assertEquals(accountId, botAccount.id, "BotAccount ID does not match expectations.")
|
|
||||||
assertEquals(creatorId, botAccount.creatorId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AppPathsTest {
|
internal class AppPathsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
@file:Suppress("PackageDirectoryMismatch")
|
|
||||||
|
|
||||||
package net.lamgc.scalabot.util
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import com.google.gson.JsonParseException
|
|
||||||
import com.google.gson.JsonPrimitive
|
|
||||||
import org.eclipse.aether.artifact.DefaultArtifact
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
internal class ArtifactSerializerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun badJsonType() {
|
|
||||||
assertFailsWith<JsonParseException> { ArtifactSerializer.deserialize(JsonObject(), null, null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Basic format serialization`() {
|
|
||||||
val gav = "org.example.software:test:1.0.0-SNAPSHOT"
|
|
||||||
val expectArtifact = DefaultArtifact(gav)
|
|
||||||
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
|
||||||
assertEquals(expectArtifact, actualArtifact)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Full format serialization`() {
|
|
||||||
val gav = "org.example.software:test:war:javadoc:1.0.0-SNAPSHOT"
|
|
||||||
val expectArtifact = DefaultArtifact(gav)
|
|
||||||
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
|
||||||
assertEquals(expectArtifact, actualArtifact)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deserialize() {
|
|
||||||
val gav = "org.example.software:test:1.0.0-SNAPSHOT"
|
|
||||||
val expectArtifact = DefaultArtifact(gav)
|
|
||||||
val actualArtifact = ArtifactSerializer.deserialize(JsonPrimitive(gav), null, null)
|
|
||||||
assertEquals(expectArtifact, actualArtifact)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,325 +0,0 @@
|
|||||||
package util
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.verify
|
|
||||||
import net.lamgc.scalabot.MavenRepositoryConfig
|
|
||||||
import net.lamgc.scalabot.util.AuthenticationSerializer
|
|
||||||
import net.lamgc.scalabot.util.MavenRepositoryConfigSerializer
|
|
||||||
import net.lamgc.scalabot.util.ProxyTypeSerializer
|
|
||||||
import org.eclipse.aether.repository.Authentication
|
|
||||||
import org.eclipse.aether.repository.AuthenticationContext
|
|
||||||
import org.eclipse.aether.repository.Proxy
|
|
||||||
import org.intellij.lang.annotations.Language
|
|
||||||
import org.junit.jupiter.api.Assertions.assertThrows
|
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
import java.net.URL
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
internal class SerializersKtTest {
|
|
||||||
|
|
||||||
private val instance: Any
|
|
||||||
private val method: Method
|
|
||||||
|
|
||||||
init {
|
|
||||||
val clazz = Class.forName("net.lamgc.scalabot.util.SerializerUtils")
|
|
||||||
method = clazz.getDeclaredMethod("checkJsonKey", JsonObject::class.java, String::class.java)
|
|
||||||
method.isAccessible = true
|
|
||||||
instance = clazz.getDeclaredField("INSTANCE").apply {
|
|
||||||
isAccessible = true
|
|
||||||
}.get(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invoke(json: JsonObject, key: String): String {
|
|
||||||
try {
|
|
||||||
return method.invoke(instance, json, key) as String
|
|
||||||
} catch (e: InvocationTargetException) {
|
|
||||||
throw e.targetException
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Json key checker test`() {
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
invoke(JsonObject(), "NOT_EXIST_KEY")
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
invoke(JsonObject().apply { add("NULL_KEY", JsonNull.INSTANCE) }, "NULL_KEY")
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
invoke(JsonObject().apply { add("ARRAY_KEY", JsonArray()) }, "ARRAY_KEY")
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
invoke(JsonObject().apply { add("OBJECT_KEY", JsonObject()) }, "OBJECT_KEY")
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectKey = "TEST"
|
|
||||||
val expectString = "testString"
|
|
||||||
val json = JsonObject().apply { addProperty(expectKey, expectString) }
|
|
||||||
|
|
||||||
assertEquals(expectString, invoke(json, expectKey))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ProxyTypeSerializerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `serialize test`() {
|
|
||||||
for (type in DefaultBotOptions.ProxyType.values()) {
|
|
||||||
assertEquals(
|
|
||||||
JsonPrimitive(type.name), ProxyTypeSerializer.serialize(type, null, null),
|
|
||||||
"ProxyType 序列化结果与预期不符."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `deserialize test`() {
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
ProxyTypeSerializer.deserialize(JsonObject(), null, null)
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
ProxyTypeSerializer.deserialize(JsonArray(), null, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
ProxyTypeSerializer.deserialize(JsonPrimitive("NOT_IN_ENUM_VALUE"), null, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
DefaultBotOptions.ProxyType.NO_PROXY,
|
|
||||||
ProxyTypeSerializer.deserialize(JsonNull.INSTANCE, null, null)
|
|
||||||
)
|
|
||||||
|
|
||||||
for (type in DefaultBotOptions.ProxyType.values()) {
|
|
||||||
assertEquals(
|
|
||||||
type, ProxyTypeSerializer.deserialize(JsonPrimitive(type.name), null, null),
|
|
||||||
"ProxyType 反序列化结果与预期不符."
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
type, ProxyTypeSerializer.deserialize(JsonPrimitive(" ${type.name} "), null, null),
|
|
||||||
"ProxyType 反序列化时未对 Json 字符串进行修剪(trim)."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class MavenRepositoryConfigSerializerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `unsupported json type deserialize test`() {
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
JsonArray(),
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
JsonNull.INSTANCE,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `json primitive deserialize test`() {
|
|
||||||
val expectRepoUrl = "https://repo.example.org/maven"
|
|
||||||
val config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
JsonPrimitive(expectRepoUrl),
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertNull(config.id)
|
|
||||||
assertEquals(URL(expectRepoUrl), config.url)
|
|
||||||
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
|
||||||
assertEquals("default", config.layout)
|
|
||||||
assertTrue(config.enableReleases)
|
|
||||||
assertTrue(config.enableSnapshots)
|
|
||||||
assertNull(config.authentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `json object default deserialize test`() {
|
|
||||||
val expectRepoUrl = "https://repo.example.org/maven"
|
|
||||||
val jsonObject = JsonObject()
|
|
||||||
jsonObject.addProperty("url", expectRepoUrl)
|
|
||||||
val config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
jsonObject,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertNull(config.id)
|
|
||||||
assertEquals(URL(expectRepoUrl), config.url)
|
|
||||||
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
|
||||||
assertEquals("default", config.layout)
|
|
||||||
assertTrue(config.enableReleases)
|
|
||||||
assertTrue(config.enableSnapshots)
|
|
||||||
assertNull(config.authentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `json object deserialize test`() {
|
|
||||||
@Language("JSON5")
|
|
||||||
val looksGoodJsonString = """
|
|
||||||
{
|
|
||||||
"id": "test-repository",
|
|
||||||
"url": "https://repo.example.org/maven",
|
|
||||||
"proxy": {
|
|
||||||
"type": "http",
|
|
||||||
"host": "127.0.1.1",
|
|
||||||
"port": 10800
|
|
||||||
},
|
|
||||||
"layout": "default",
|
|
||||||
"enableReleases": false,
|
|
||||||
"enableSnapshots": true
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
val jsonObject = Gson().fromJson(looksGoodJsonString, JsonObject::class.java)
|
|
||||||
var config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
jsonObject,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(jsonObject["id"].asString, config.id)
|
|
||||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
|
||||||
assertEquals(Proxy("http", "127.0.1.1", 10800), config.proxy)
|
|
||||||
assertEquals(jsonObject["layout"].asString, config.layout)
|
|
||||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
|
||||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
jsonObject.add("proxy", JsonNull.INSTANCE)
|
|
||||||
jsonObject.remove("layout")
|
|
||||||
|
|
||||||
config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
jsonObject,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(jsonObject["id"].asString, config.id)
|
|
||||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
|
||||||
assertNull(config.proxy)
|
|
||||||
assertEquals("default", config.layout)
|
|
||||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
|
||||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
jsonObject.add("authentication", JsonArray())
|
|
||||||
jsonObject.add("layout", mockk<JsonPrimitive> {
|
|
||||||
every { asString }.returns(null)
|
|
||||||
})
|
|
||||||
|
|
||||||
config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
jsonObject,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(jsonObject["id"].asString, config.id)
|
|
||||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
|
||||||
assertNull(config.proxy)
|
|
||||||
assertEquals("default", config.layout)
|
|
||||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
|
||||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
|
||||||
assertNull(config.authentication)
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
jsonObject.add("authentication", JsonObject().apply {
|
|
||||||
addProperty("username", "testUsername")
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
})
|
|
||||||
|
|
||||||
config = MavenRepositoryConfigSerializer.deserialize(
|
|
||||||
jsonObject,
|
|
||||||
MavenRepositoryConfig::class.java,
|
|
||||||
TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(jsonObject["id"].asString, config.id)
|
|
||||||
assertEquals(URL(jsonObject["url"].asString), config.url)
|
|
||||||
assertNull(config.proxy)
|
|
||||||
assertEquals("default", config.layout)
|
|
||||||
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
|
||||||
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
|
||||||
assertNotNull(config.authentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private object TestJsonDeserializationContext : JsonDeserializationContext {
|
|
||||||
|
|
||||||
private val gson = GsonBuilder()
|
|
||||||
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
|
||||||
.create()
|
|
||||||
|
|
||||||
override fun <T : Any?> deserialize(json: JsonElement, typeOfT: Type): T {
|
|
||||||
return gson.fromJson(json, typeOfT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AuthenticationSerializerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `deserialize test`() {
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
AuthenticationSerializer.deserialize(
|
|
||||||
JsonNull.INSTANCE,
|
|
||||||
Authentication::class.java, TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
AuthenticationSerializer.deserialize(
|
|
||||||
JsonArray(),
|
|
||||||
Authentication::class.java, TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
assertThrows(JsonParseException::class.java) {
|
|
||||||
AuthenticationSerializer.deserialize(
|
|
||||||
JsonPrimitive("A STRING"),
|
|
||||||
Authentication::class.java, TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectJsonObject = JsonObject().apply {
|
|
||||||
addProperty("username", "testUsername")
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
}
|
|
||||||
|
|
||||||
val mockContext = mockk<AuthenticationContext> {
|
|
||||||
every { put(any(), any()) }.answers { }
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = AuthenticationSerializer.deserialize(
|
|
||||||
expectJsonObject,
|
|
||||||
Authentication::class.java, TestJsonDeserializationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
assertNotNull(result)
|
|
||||||
result.fill(mockContext, "username", null)
|
|
||||||
result.fill(mockContext, "password", null)
|
|
||||||
|
|
||||||
verify {
|
|
||||||
mockContext.put("username", "testUsername")
|
|
||||||
mockContext.put("password", "testPassword".toCharArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
package net.lamgc.scalabot.util
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
class UsernameAuthenticatorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun checkCredentialsTest() {
|
|
||||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
|
||||||
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
|
||||||
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
|
||||||
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun toJsonObjectTest() {
|
|
||||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
|
||||||
val jsonObject = authenticator.toJsonObject()
|
|
||||||
assertEquals("testUser", jsonObject["username"]?.asString)
|
|
||||||
assertEquals("testPassword", jsonObject["password"]?.asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun equalsTest() {
|
|
||||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
|
||||||
assertEquals(authenticator, UsernameAuthenticator("testUser", "testPassword"))
|
|
||||||
assertEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "testPassword").hashCode())
|
|
||||||
assertNotEquals(authenticator, UsernameAuthenticator("testUser", "falsePassword"))
|
|
||||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "falsePassword").hashCode())
|
|
||||||
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "testPassword"))
|
|
||||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "testPassword").hashCode())
|
|
||||||
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "falsePassword"))
|
|
||||||
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "falsePassword").hashCode())
|
|
||||||
assertFalse(authenticator.equals(null))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class UsernameAuthenticatorSerializerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun serializeTest() {
|
|
||||||
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
|
||||||
val jsonElement = UsernameAuthenticatorSerializer.serialize(authenticator, null, null)
|
|
||||||
assertTrue(jsonElement.isJsonObject)
|
|
||||||
val jsonObject = jsonElement.asJsonObject
|
|
||||||
assertEquals("testUser", jsonObject["username"]?.asString)
|
|
||||||
assertEquals("testPassword", jsonObject["password"]?.asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deserializeTest() {
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonArray(), null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonPrimitive(""), null, null)
|
|
||||||
}
|
|
||||||
assertNull(UsernameAuthenticatorSerializer.deserialize(JsonNull.INSTANCE, null, null))
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "testUser")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "testUser")
|
|
||||||
add("password", JsonArray())
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
add("username", JsonArray())
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "")
|
|
||||||
addProperty("password", "")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "testUser")
|
|
||||||
addProperty("password", "")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
assertThrows<JsonParseException> {
|
|
||||||
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "")
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
}, null, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
val authenticator = UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
|
||||||
addProperty("username", "testUser")
|
|
||||||
addProperty("password", "testPassword")
|
|
||||||
}, null, null)
|
|
||||||
assertNotNull(authenticator)
|
|
||||||
|
|
||||||
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
|
||||||
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
|
||||||
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
112
scalabot-meta/build.gradle.kts
Normal file
112
scalabot-meta/build.gradle.kts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "1.6.10"
|
||||||
|
id("org.jetbrains.kotlinx.kover") version "0.5.1"
|
||||||
|
id("org.jetbrains.dokka") version "1.7.0"
|
||||||
|
`maven-publish`
|
||||||
|
signing
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val aetherVersion = "1.1.0"
|
||||||
|
implementation("org.eclipse.aether:aether-api:$aetherVersion")
|
||||||
|
implementation("org.eclipse.aether:aether-util:$aetherVersion")
|
||||||
|
|
||||||
|
implementation("org.telegram:telegrambots-meta:6.0.1")
|
||||||
|
|
||||||
|
implementation("com.google.code.gson:gson:2.9.0")
|
||||||
|
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
testImplementation("io.mockk:mockk:1.12.4")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
||||||
|
|
||||||
|
dokkaHtmlPlugin("org.jetbrains.dokka:javadoc-plugin:1.7.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withJavadocJar()
|
||||||
|
withSourcesJar()
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.getByName<Test>("test") {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
val javadocJar = tasks.named<Jar>("javadocJar") {
|
||||||
|
from(tasks.named("dokkaJavadoc"))
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
if (project.version.toString().endsWith("-SNAPSHOT", ignoreCase = true)) {
|
||||||
|
maven("https://nexus.kuku.me/repository/maven-snapshots/") {
|
||||||
|
credentials {
|
||||||
|
username = project.properties["repo.credentials.private.username"].toString()
|
||||||
|
password = project.properties["repo.credentials.private.password"].toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maven("https://nexus.kuku.me/repository/maven-releases/") {
|
||||||
|
credentials {
|
||||||
|
username = project.properties["repo.credentials.private.username"].toString()
|
||||||
|
password = project.properties["repo.credentials.private.password"].toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
from(components["kotlin"])
|
||||||
|
artifact(javadocJar)
|
||||||
|
artifact(tasks.named("sourcesJar"))
|
||||||
|
pom {
|
||||||
|
name.set("ScalaBot-meta")
|
||||||
|
description.set(
|
||||||
|
"Shared components used by scalabot (such as configuration classes)"
|
||||||
|
)
|
||||||
|
url.set("https://github.com/LamGC/ScalaBot")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("The MIT License")
|
||||||
|
url.set("https://www.opensource.org/licenses/mit-license.php")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("LamGC")
|
||||||
|
name.set("LamGC")
|
||||||
|
email.set("lam827@lamgc.net")
|
||||||
|
url.set("https://github.com/LamGC")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:https://github.com/LamGC/ScalaBot.git")
|
||||||
|
developerConnection.set("scm:git:https://github.com/LamGC/ScalaBot.git")
|
||||||
|
url.set("https://github.com/LamGC/ScalaBot")
|
||||||
|
}
|
||||||
|
issueManagement {
|
||||||
|
url.set("https://github.com/LamGC/ScalaBot/issues")
|
||||||
|
system.set("Github Issues")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
useGpgCmd()
|
||||||
|
sign(publishing.publications["maven"])
|
||||||
|
}
|
131
scalabot-meta/src/main/kotlin/Configs.kt
Normal file
131
scalabot-meta/src/main/kotlin/Configs.kt
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package net.lamgc.scalabot.config
|
||||||
|
|
||||||
|
import org.eclipse.aether.artifact.Artifact
|
||||||
|
import org.eclipse.aether.repository.Authentication
|
||||||
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import org.telegram.telegrambots.meta.ApiConstants
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机器人帐号信息.
|
||||||
|
* @property name 机器人名称, 建议与实际设定的名称相同.
|
||||||
|
* @property token 机器人 API Token.
|
||||||
|
* @property creatorId 机器人创建者, 管理机器人需要使用该信息.
|
||||||
|
* @property id 机器人账号 ID.
|
||||||
|
*/
|
||||||
|
data class BotAccount(
|
||||||
|
val name: String,
|
||||||
|
val token: String,
|
||||||
|
val creatorId: Long
|
||||||
|
) {
|
||||||
|
|
||||||
|
val id
|
||||||
|
// 不要想着每次获取都要从 token 里取出有性能损耗.
|
||||||
|
// 由于 Gson 解析方式, 如果不这么做, 会出现 token 设置前 id 初始化完成, 就只有"0"了,
|
||||||
|
// 虽然能过单元测试, 但实际使用过程是不能正常用的.
|
||||||
|
get() = token.substringBefore(":").toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机器人配置.
|
||||||
|
* @property enabled 是否启用机器人.
|
||||||
|
* @property account 机器人帐号信息, 用于访问 API.
|
||||||
|
* @property disableBuiltInAbility 是否禁用 AbilityBot 自带命令.
|
||||||
|
* @property autoUpdateCommandList 是否自动更新机器人在 Telegram 的命令列表.
|
||||||
|
* @property extensions 该机器人启用的扩展.
|
||||||
|
* @property proxy 为该机器人单独设置的代理配置, 如无设置, 则使用 AppConfig 中的代理配置.
|
||||||
|
* @property baseApiUrl 机器人所使用的 API 地址, 适用于自建 Telegram Bot API 端点.
|
||||||
|
*/
|
||||||
|
data class BotConfig(
|
||||||
|
val enabled: Boolean = false,
|
||||||
|
val account: BotAccount,
|
||||||
|
val disableBuiltInAbility: Boolean = false,
|
||||||
|
val autoUpdateCommandList: Boolean = false,
|
||||||
|
/*
|
||||||
|
* 使用构件坐标来选择机器人所使用的扩展包.
|
||||||
|
* 这么做的原因是我暂时没找到一个合适的方法来让开发者方便地设定自己的扩展 Id,
|
||||||
|
* 而构件坐标(POM Reference 或者叫 GAV 坐标)是开发者创建 Maven/Gradle 项目时一定会设置的,
|
||||||
|
* 所以就直接用了. :P
|
||||||
|
*/
|
||||||
|
val extensions: Set<Artifact> = emptySet(),
|
||||||
|
val proxy: ProxyConfig = ProxyConfig(type = ProxyType.NO_PROXY),
|
||||||
|
val baseApiUrl: String = ApiConstants.BASE_URL
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代理类型.
|
||||||
|
*/
|
||||||
|
enum class ProxyType {
|
||||||
|
NO_PROXY,
|
||||||
|
HTTP,
|
||||||
|
HTTPS,
|
||||||
|
SOCKS4,
|
||||||
|
SOCKS5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代理配置.
|
||||||
|
* @property type 代理类型.
|
||||||
|
* @property host 代理服务端地址.
|
||||||
|
* @property port 代理服务端端口.
|
||||||
|
*/
|
||||||
|
data class ProxyConfig(
|
||||||
|
val type: ProxyType = ProxyType.NO_PROXY,
|
||||||
|
val host: String = "127.0.0.1",
|
||||||
|
val port: Int = 1080
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ScalaBot 的运行指标公开配置.
|
||||||
|
*
|
||||||
|
* ScalaBot 内置了用于公开运行指标的服务端,
|
||||||
|
* 该指标遵循 Prometheus 的标准, 可以通过 Prometheus 的工具来查看.
|
||||||
|
*
|
||||||
|
* @property enable 是否启用运行指标服务端.
|
||||||
|
* @property port 运行指标服务端的端口.
|
||||||
|
* @property bindAddress 运行指标服务端的绑定地址, 绑定后只有该地址可以访问.
|
||||||
|
* @property authenticator 运行指标服务端的 HTTP 认证配置.
|
||||||
|
*/
|
||||||
|
data class MetricsConfig(
|
||||||
|
val enable: Boolean = false,
|
||||||
|
val port: Int = 9386,
|
||||||
|
val bindAddress: String? = "0.0.0.0",
|
||||||
|
val authenticator: UsernameAuthenticator? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maven 远端仓库配置.
|
||||||
|
* @property id 远端仓库 ID, 如果该属性未配置 (null), 那么运行时将会自动分配一个 Id.
|
||||||
|
* @property url 仓库地址.
|
||||||
|
* @property proxy 访问仓库所使用的代理, 仅支持 http/https 代理.
|
||||||
|
* @property layout 仓库布局版本, Maven 2 及以上使用 `default`, Maven 1 使用 `legacy`.
|
||||||
|
* @property enableReleases 是否在该远端仓库获取发布版本.
|
||||||
|
* @property enableSnapshots 是否在该远端仓库获取快照版本.
|
||||||
|
* @property authentication 访问该远端仓库所使用的认证配置.
|
||||||
|
*/
|
||||||
|
data class MavenRepositoryConfig(
|
||||||
|
val id: String? = null,
|
||||||
|
val url: URL,
|
||||||
|
val proxy: Proxy? = null,
|
||||||
|
val layout: String = "default",
|
||||||
|
val enableReleases: Boolean = true,
|
||||||
|
val enableSnapshots: Boolean = true,
|
||||||
|
// 可能要设计个 type 来判断解析成什么类型的 Authentication.
|
||||||
|
val authentication: Authentication? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ScalaBot App 配置.
|
||||||
|
*
|
||||||
|
* App 配置信息与 BotConfig 分开, 分别存储在各自单独的文件中.
|
||||||
|
* @property proxy Telegram API 代理配置.
|
||||||
|
* @property metrics 运行指标数据配置. 可通过时序数据库记录运行数据.
|
||||||
|
* @property mavenRepositories Maven 远端仓库配置.
|
||||||
|
* @property mavenLocalRepository Maven 本地仓库路径. 相对于运行目录 (而不是 DATA_ROOT 目录)
|
||||||
|
*/
|
||||||
|
data class AppConfig(
|
||||||
|
val proxy: ProxyConfig = ProxyConfig(),
|
||||||
|
val metrics: MetricsConfig = MetricsConfig(),
|
||||||
|
val mavenRepositories: List<MavenRepositoryConfig> = emptyList(),
|
||||||
|
val mavenLocalRepository: String? = null
|
||||||
|
)
|
26
scalabot-meta/src/main/kotlin/UsernameAuthenticator.kt
Normal file
26
scalabot-meta/src/main/kotlin/UsernameAuthenticator.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package net.lamgc.scalabot.config
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.sun.net.httpserver.BasicAuthenticator
|
||||||
|
|
||||||
|
class UsernameAuthenticator(private val username: String, private val password: String) :
|
||||||
|
BasicAuthenticator("metrics") {
|
||||||
|
override fun checkCredentials(username: String?, password: String?): Boolean =
|
||||||
|
this.username == username && this.password == password
|
||||||
|
|
||||||
|
fun toJsonObject(): JsonObject = JsonObject().apply {
|
||||||
|
addProperty("username", username)
|
||||||
|
addProperty("password", password)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other is UsernameAuthenticator && this.username == other.username && this.password == other.password
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = username.hashCode()
|
||||||
|
result = 31 * result + password.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
262
scalabot-meta/src/main/kotlin/serializer/Serializer.kt
Normal file
262
scalabot-meta/src/main/kotlin/serializer/Serializer.kt
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
package net.lamgc.scalabot.config.serializer
|
||||||
|
|
||||||
|
import com.google.gson.*
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import net.lamgc.scalabot.config.*
|
||||||
|
import org.eclipse.aether.artifact.AbstractArtifact
|
||||||
|
import org.eclipse.aether.artifact.Artifact
|
||||||
|
import org.eclipse.aether.artifact.DefaultArtifact
|
||||||
|
import org.eclipse.aether.repository.Authentication
|
||||||
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import org.eclipse.aether.util.repository.AuthenticationBuilder
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.net.MalformedURLException
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
object ProxyTypeSerializer : JsonDeserializer<ProxyType>,
|
||||||
|
JsonSerializer<ProxyType> {
|
||||||
|
|
||||||
|
override fun deserialize(
|
||||||
|
json: JsonElement,
|
||||||
|
typeOfT: Type?,
|
||||||
|
context: JsonDeserializationContext?
|
||||||
|
): ProxyType {
|
||||||
|
if (json.isJsonNull) {
|
||||||
|
return ProxyType.NO_PROXY
|
||||||
|
}
|
||||||
|
if (!json.isJsonPrimitive) {
|
||||||
|
throw JsonParseException("Wrong configuration value type.")
|
||||||
|
}
|
||||||
|
val value = json.asString.trim()
|
||||||
|
try {
|
||||||
|
return ProxyType.valueOf(value.uppercase())
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw JsonParseException("Invalid value: $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(
|
||||||
|
src: ProxyType,
|
||||||
|
typeOfSrc: Type?,
|
||||||
|
context: JsonSerializationContext?
|
||||||
|
): JsonElement {
|
||||||
|
return JsonPrimitive(src.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ArtifactSerializer : JsonSerializer<Artifact>, JsonDeserializer<Artifact> {
|
||||||
|
override fun serialize(src: Artifact, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
|
||||||
|
return if (src is AbstractArtifact) {
|
||||||
|
JsonPrimitive(src.toString())
|
||||||
|
} else {
|
||||||
|
JsonPrimitive(
|
||||||
|
DefaultArtifact(
|
||||||
|
src.groupId,
|
||||||
|
src.artifactId,
|
||||||
|
src.classifier,
|
||||||
|
src.extension,
|
||||||
|
src.version
|
||||||
|
).toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Artifact {
|
||||||
|
if (!json.isJsonPrimitive) {
|
||||||
|
throw JsonParseException("Wrong configuration value type.")
|
||||||
|
}
|
||||||
|
val artifactStr = json.asString.trim()
|
||||||
|
try {
|
||||||
|
return DefaultArtifact(artifactStr)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw JsonParseException("Invalid artifact format: `${artifactStr}`.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object AuthenticationSerializer : JsonDeserializer<Authentication> {
|
||||||
|
|
||||||
|
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Authentication {
|
||||||
|
if (json !is JsonObject) {
|
||||||
|
throw JsonParseException("Unsupported JSON type.")
|
||||||
|
}
|
||||||
|
val username = SerializerUtils.checkJsonKey(json, "username")
|
||||||
|
val password = SerializerUtils.checkJsonKey(json, "password")
|
||||||
|
val builder = AuthenticationBuilder()
|
||||||
|
builder.addUsername(username)
|
||||||
|
builder.addPassword(password)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private object SerializerUtils {
|
||||||
|
fun checkJsonKey(json: JsonObject, key: String): String {
|
||||||
|
if (!json.has(key)) {
|
||||||
|
throw JsonParseException("Required field does not exist: $key")
|
||||||
|
} else if (!json.get(key).isJsonPrimitive) {
|
||||||
|
throw JsonParseException("Wrong field `$key` type: ${json.get(key)::class.java}")
|
||||||
|
}
|
||||||
|
return json.get(key).asString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object MavenRepositoryConfigSerializer
|
||||||
|
: JsonDeserializer<MavenRepositoryConfig> {
|
||||||
|
|
||||||
|
override fun deserialize(
|
||||||
|
json: JsonElement,
|
||||||
|
typeOfT: Type,
|
||||||
|
context: JsonDeserializationContext
|
||||||
|
): MavenRepositoryConfig {
|
||||||
|
return when (json) {
|
||||||
|
is JsonObject -> {
|
||||||
|
MavenRepositoryConfig(
|
||||||
|
id = json.get("id")?.asString,
|
||||||
|
url = URL(SerializerUtils.checkJsonKey(json, "url")),
|
||||||
|
proxy = if (json.has("proxy"))
|
||||||
|
context.deserialize<Proxy>(
|
||||||
|
json.get("proxy"), Proxy::class.java
|
||||||
|
) else null,
|
||||||
|
layout = json.get("layout")?.asString ?: "default",
|
||||||
|
enableReleases = json.get("enableReleases")?.asBoolean ?: true,
|
||||||
|
enableSnapshots = json.get("enableSnapshots")?.asBoolean ?: true,
|
||||||
|
authentication = if (json.has("authentication"))
|
||||||
|
context.deserialize<Authentication>(
|
||||||
|
json.get("authentication"), Authentication::class.java
|
||||||
|
) else null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is JsonPrimitive -> {
|
||||||
|
try {
|
||||||
|
return MavenRepositoryConfig(url = URL(json.asString))
|
||||||
|
} catch (e: MalformedURLException) {
|
||||||
|
throw JsonParseException("Invalid URL: ${json.asString}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw JsonParseException("Unsupported Maven repository configuration type. (Only support JSON object or url string)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object UsernameAuthenticatorSerializer : JsonSerializer<UsernameAuthenticator>,
|
||||||
|
JsonDeserializer<UsernameAuthenticator> {
|
||||||
|
|
||||||
|
override fun serialize(
|
||||||
|
src: UsernameAuthenticator,
|
||||||
|
typeOfSrc: Type?,
|
||||||
|
context: JsonSerializationContext?
|
||||||
|
): JsonElement {
|
||||||
|
return src.toJsonObject()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(
|
||||||
|
json: JsonElement,
|
||||||
|
typeOfT: Type?,
|
||||||
|
context: JsonDeserializationContext?
|
||||||
|
): UsernameAuthenticator? {
|
||||||
|
if (json.isJsonNull) {
|
||||||
|
return null
|
||||||
|
} else if (!json.isJsonObject) {
|
||||||
|
throw JsonParseException("Invalid attribute value type.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val jsonObj = json.asJsonObject
|
||||||
|
|
||||||
|
if (jsonObj["username"]?.isJsonPrimitive != true) {
|
||||||
|
throw JsonParseException("Invalid attribute value: username")
|
||||||
|
} else if (jsonObj["password"]?.isJsonPrimitive != true) {
|
||||||
|
throw JsonParseException("Invalid attribute value: password")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObj["username"].asString.isEmpty() || jsonObj["password"].asString.isEmpty()) {
|
||||||
|
throw JsonParseException("`username` or `password` is empty.")
|
||||||
|
}
|
||||||
|
return UsernameAuthenticator(jsonObj["username"].asString, jsonObj["password"].asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object ProxyConfigSerializer : JsonSerializer<ProxyConfig>, JsonDeserializer<ProxyConfig> {
|
||||||
|
override fun serialize(src: ProxyConfig?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
|
||||||
|
if (src == null) {
|
||||||
|
return JsonNull.INSTANCE
|
||||||
|
}
|
||||||
|
return JsonObject().apply {
|
||||||
|
addProperty("type", src.type.name)
|
||||||
|
addProperty("host", src.host)
|
||||||
|
addProperty("port", src.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): ProxyConfig {
|
||||||
|
if (json == null || json.isJsonNull) {
|
||||||
|
return ProxyConfig()
|
||||||
|
} else if (json !is JsonObject) {
|
||||||
|
throw JsonParseException("Invalid json type.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val typeStr = json["type"]?.asString ?: return ProxyConfig()
|
||||||
|
val type = try {
|
||||||
|
ProxyType.valueOf(typeStr)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw JsonParseException("Invalid proxy type: `$typeStr`")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json.has("host") || !json.has("port")) {
|
||||||
|
throw JsonParseException("Missing `host` field or `port` field.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProxyConfig(
|
||||||
|
type = type,
|
||||||
|
host = json["host"].asString,
|
||||||
|
port = json["port"].asInt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object BotConfigSerializer : JsonSerializer<BotConfig>, JsonDeserializer<BotConfig> {
|
||||||
|
|
||||||
|
private val defaultConfig = BotConfig(account = BotAccount("__Default__", "__Default__", 0))
|
||||||
|
|
||||||
|
override fun serialize(src: BotConfig, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||||
|
return JsonObject().apply {
|
||||||
|
addProperty("enabled", src.enabled)
|
||||||
|
add("account", context.serialize(src.account))
|
||||||
|
addProperty("disableBuiltInAbility", src.disableBuiltInAbility)
|
||||||
|
addProperty("autoUpdateCommandList", src.autoUpdateCommandList)
|
||||||
|
add("extensions", context.serialize(src.extensions))
|
||||||
|
add("proxy", ProxyConfigSerializer.serialize(src.proxy, ProxyConfig::class.java, context))
|
||||||
|
addProperty("baseApiUrl", src.baseApiUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): BotConfig {
|
||||||
|
if (json !is JsonObject) {
|
||||||
|
throw JsonParseException("Unsupported JSON type.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json.has("account")) {
|
||||||
|
throw JsonParseException("Missing `account` field.")
|
||||||
|
} else if (!json.get("account").isJsonObject) {
|
||||||
|
throw JsonParseException("Invalid `account` field type.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 json 反序列化 BotConfig(使用构造函数)
|
||||||
|
return BotConfig(
|
||||||
|
enabled = json.get("enabled")?.asBoolean ?: defaultConfig.enabled,
|
||||||
|
account = context.deserialize(json.get("account"), BotAccount::class.java)!!,
|
||||||
|
disableBuiltInAbility = json.get("disableBuiltInAbility")?.asBoolean ?: defaultConfig.disableBuiltInAbility,
|
||||||
|
autoUpdateCommandList = json.get("autoUpdateCommandList")?.asBoolean ?: defaultConfig.autoUpdateCommandList,
|
||||||
|
extensions = context.deserialize(json.get("extensions"), object : TypeToken<Set<Artifact>>() {}.type)
|
||||||
|
?: defaultConfig.extensions,
|
||||||
|
proxy = context.deserialize(json.get("proxy"), ProxyConfig::class.java) ?: defaultConfig.proxy,
|
||||||
|
baseApiUrl = json.get("baseApiUrl")?.asString ?: defaultConfig.baseApiUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
516
scalabot-meta/src/test/kotlin/ConfigsTest.kt
Normal file
516
scalabot-meta/src/test/kotlin/ConfigsTest.kt
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
package net.lamgc.scalabot.config
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import net.lamgc.scalabot.config.serializer.*
|
||||||
|
import org.eclipse.aether.artifact.Artifact
|
||||||
|
import org.eclipse.aether.artifact.DefaultArtifact
|
||||||
|
import org.eclipse.aether.repository.Authentication
|
||||||
|
import org.eclipse.aether.repository.AuthenticationContext
|
||||||
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
internal class BotAccountTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `id getter`() {
|
||||||
|
val accountId = abs(Random().nextInt()).toLong()
|
||||||
|
Assertions.assertEquals(accountId, BotAccount("Test", "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", 0).id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deserializerTest() {
|
||||||
|
val accountId = abs(Random().nextInt()).toLong()
|
||||||
|
val creatorId = abs(Random().nextInt()).toLong()
|
||||||
|
val botAccountJsonObject = gson.fromJson(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"name": "TestBot",
|
||||||
|
"token": "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||||
|
"creatorId": $creatorId
|
||||||
|
}
|
||||||
|
""".trimIndent(), JsonObject::class.java
|
||||||
|
)
|
||||||
|
val botAccount = Gson().fromJson(botAccountJsonObject, BotAccount::class.java)
|
||||||
|
assertEquals(accountId, botAccount.id)
|
||||||
|
assertEquals("TestBot", botAccount.name)
|
||||||
|
assertEquals(creatorId, botAccount.creatorId)
|
||||||
|
assertEquals("${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", botAccount.token)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun serializerTest() {
|
||||||
|
val accountId = abs(Random().nextInt()).toLong()
|
||||||
|
val creatorId = abs(Random().nextInt()).toLong()
|
||||||
|
val botAccount = BotAccount("TestBot", "${accountId}:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", creatorId)
|
||||||
|
val botAccountJsonObject = gson.toJsonTree(botAccount)
|
||||||
|
assertTrue(botAccountJsonObject is JsonObject)
|
||||||
|
assertEquals(botAccount.name, botAccountJsonObject["name"].asString)
|
||||||
|
assertEquals(botAccount.token, botAccountJsonObject["token"].asString)
|
||||||
|
assertNull(botAccountJsonObject["id"])
|
||||||
|
Assertions.assertEquals(creatorId, botAccountJsonObject["creatorId"].asLong)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BotConfigTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(BotConfig::class.java, BotConfigSerializer)
|
||||||
|
.registerTypeAdapter(Artifact::class.java, ArtifactSerializer)
|
||||||
|
.registerTypeAdapter(ProxyConfig::class.java, ProxyConfigSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serialize`() {
|
||||||
|
val minimumExpectConfig = BotConfig(
|
||||||
|
account = BotAccount(
|
||||||
|
name = "TestBot",
|
||||||
|
token = "123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||||
|
creatorId = 123456789L
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = gson.toJsonTree(minimumExpectConfig)
|
||||||
|
assertTrue(json is JsonObject)
|
||||||
|
assertEquals(minimumExpectConfig.enabled, json.get("enabled").asBoolean)
|
||||||
|
|
||||||
|
assertEquals(minimumExpectConfig.account.name, json.get("account").asJsonObject.get("name").asString)
|
||||||
|
assertEquals(minimumExpectConfig.account.token, json.get("account").asJsonObject.get("token").asString)
|
||||||
|
assertEquals(minimumExpectConfig.account.creatorId, json.get("account").asJsonObject.get("creatorId").asLong)
|
||||||
|
assertNull(json.get("account").asJsonObject.get("id"))
|
||||||
|
|
||||||
|
assertEquals(minimumExpectConfig.proxy.host, json.get("proxy").asJsonObject.get("host").asString)
|
||||||
|
assertEquals(minimumExpectConfig.proxy.port, json.get("proxy").asJsonObject.get("port").asInt)
|
||||||
|
assertEquals(minimumExpectConfig.proxy.type.name, json.get("proxy").asJsonObject.get("type").asString)
|
||||||
|
|
||||||
|
assertEquals(minimumExpectConfig.disableBuiltInAbility, json.get("disableBuiltInAbility").asBoolean)
|
||||||
|
assertEquals(minimumExpectConfig.autoUpdateCommandList, json.get("autoUpdateCommandList").asBoolean)
|
||||||
|
|
||||||
|
assertNotNull(json.get("extensions"))
|
||||||
|
assertTrue(json.get("extensions").isJsonArray)
|
||||||
|
assertTrue(json.get("extensions").asJsonArray.isEmpty)
|
||||||
|
|
||||||
|
assertEquals(minimumExpectConfig.baseApiUrl, json.get("baseApiUrl").asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserialize`() {
|
||||||
|
val expectExtensionArtifact = DefaultArtifact("org.example.test:test-extension:1.0.0")
|
||||||
|
@Language("JSON5") val looksGoodJson = """
|
||||||
|
{
|
||||||
|
"enabled": false,
|
||||||
|
"account": {
|
||||||
|
"name": "TestBot",
|
||||||
|
"token": "123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||||
|
"creatorId": 123456789
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 8080,
|
||||||
|
"type": "HTTP"
|
||||||
|
},
|
||||||
|
"disableBuiltInAbility": false,
|
||||||
|
"autoUpdateCommandList": true,
|
||||||
|
"extensions": [
|
||||||
|
"$expectExtensionArtifact"
|
||||||
|
],
|
||||||
|
"baseApiUrl": "http://localhost:8080"
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val actualConfig = gson.fromJson(looksGoodJson, BotConfig::class.java)
|
||||||
|
|
||||||
|
assertEquals(false, actualConfig.enabled)
|
||||||
|
|
||||||
|
assertEquals("TestBot", actualConfig.account.name)
|
||||||
|
assertEquals("123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", actualConfig.account.token)
|
||||||
|
assertEquals(123456789L, actualConfig.account.creatorId)
|
||||||
|
|
||||||
|
assertEquals("localhost", actualConfig.proxy.host)
|
||||||
|
assertEquals(8080, actualConfig.proxy.port)
|
||||||
|
assertEquals(ProxyType.HTTP, actualConfig.proxy.type)
|
||||||
|
|
||||||
|
assertEquals(false, actualConfig.disableBuiltInAbility)
|
||||||
|
assertEquals(true, actualConfig.autoUpdateCommandList)
|
||||||
|
|
||||||
|
assertEquals(1, actualConfig.extensions.size)
|
||||||
|
assertEquals(expectExtensionArtifact, actualConfig.extensions.first())
|
||||||
|
|
||||||
|
assertEquals("http://localhost:8080", actualConfig.baseApiUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserialize - minimum parameters`() {
|
||||||
|
@Language("JSON5") val minimumLooksGoodJson = """
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"name": "TestBot",
|
||||||
|
"token": "123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10",
|
||||||
|
"creatorId": 123456789
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
val expectDefaultConfig = BotConfig(account = BotAccount("Test", "Test", 0))
|
||||||
|
val actualMinimumConfig = gson.fromJson(minimumLooksGoodJson, BotConfig::class.java)
|
||||||
|
assertNotNull(actualMinimumConfig)
|
||||||
|
assertEquals("TestBot", actualMinimumConfig.account.name)
|
||||||
|
assertEquals("123456789:AAHErDroUTznQsOd_oZPJ6cQEj4Z5mGHO10", actualMinimumConfig.account.token)
|
||||||
|
assertEquals(123456789, actualMinimumConfig.account.creatorId)
|
||||||
|
|
||||||
|
assertEquals(expectDefaultConfig.enabled, actualMinimumConfig.enabled)
|
||||||
|
assertEquals(expectDefaultConfig.disableBuiltInAbility, actualMinimumConfig.disableBuiltInAbility)
|
||||||
|
assertEquals(expectDefaultConfig.autoUpdateCommandList, actualMinimumConfig.autoUpdateCommandList)
|
||||||
|
assertEquals(expectDefaultConfig.proxy, actualMinimumConfig.proxy)
|
||||||
|
assertEquals(expectDefaultConfig.baseApiUrl, actualMinimumConfig.baseApiUrl)
|
||||||
|
|
||||||
|
assertTrue(expectDefaultConfig.extensions.containsAll(actualMinimumConfig.extensions))
|
||||||
|
assertTrue(actualMinimumConfig.extensions.containsAll(expectDefaultConfig.extensions))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ProxyConfigTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(ProxyConfig::class.java, ProxyConfigSerializer)
|
||||||
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serialize`() {
|
||||||
|
val proxyConfig = ProxyConfig(
|
||||||
|
host = "localhost",
|
||||||
|
port = 8080,
|
||||||
|
type = ProxyType.HTTP
|
||||||
|
)
|
||||||
|
val json = gson.toJsonTree(proxyConfig)
|
||||||
|
assertTrue(json is JsonObject)
|
||||||
|
assertEquals(proxyConfig.host, json.get("host").asString)
|
||||||
|
assertEquals(proxyConfig.port, json.get("port").asInt)
|
||||||
|
assertEquals(proxyConfig.type.name, json.get("type").asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserialize`() {
|
||||||
|
@Language("JSON5") val looksGoodJson = """
|
||||||
|
{
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 8080,
|
||||||
|
"type": "HTTP"
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val actualConfig = gson.fromJson(looksGoodJson, ProxyConfig::class.java)
|
||||||
|
|
||||||
|
assertEquals("localhost", actualConfig.host)
|
||||||
|
assertEquals(8080, actualConfig.port)
|
||||||
|
assertEquals(ProxyType.HTTP, actualConfig.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MetricsConfigTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(UsernameAuthenticator::class.java, UsernameAuthenticatorSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serializer`() {
|
||||||
|
val config = MetricsConfig(
|
||||||
|
enable = true,
|
||||||
|
port = 8800,
|
||||||
|
bindAddress = "127.0.0.1",
|
||||||
|
authenticator = UsernameAuthenticator(
|
||||||
|
username = "username",
|
||||||
|
password = "password"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = gson.toJsonTree(config).asJsonObject
|
||||||
|
|
||||||
|
assertEquals(config.enable, json.get("enable").asBoolean)
|
||||||
|
assertEquals(config.port, json.get("port").asInt)
|
||||||
|
assertEquals(config.bindAddress, json.get("bindAddress").asString)
|
||||||
|
assertNotNull(config.authenticator)
|
||||||
|
assertTrue(
|
||||||
|
config.authenticator!!.checkCredentials(
|
||||||
|
json.get("authenticator").asJsonObject.get("username").asString,
|
||||||
|
json.get("authenticator").asJsonObject.get("password").asString
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val expectDefaultValueConfig = MetricsConfig()
|
||||||
|
val defaultValueJson = gson.toJsonTree(expectDefaultValueConfig).asJsonObject
|
||||||
|
assertEquals(expectDefaultValueConfig.enable, defaultValueJson.get("enable").asBoolean)
|
||||||
|
assertEquals(expectDefaultValueConfig.port, defaultValueJson.get("port").asInt)
|
||||||
|
assertEquals(expectDefaultValueConfig.bindAddress, defaultValueJson.get("bindAddress").asString)
|
||||||
|
assertNull(defaultValueJson.get("authenticator"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserializer`() {
|
||||||
|
val json = """
|
||||||
|
{
|
||||||
|
"enable": true,
|
||||||
|
"port": 8800,
|
||||||
|
"bindAddress": "127.0.0.1",
|
||||||
|
"authenticator": {
|
||||||
|
"username": "username",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
val config = gson.fromJson(json, MetricsConfig::class.java)
|
||||||
|
assertEquals(true, config.enable)
|
||||||
|
assertEquals(8800, config.port)
|
||||||
|
assertEquals("127.0.0.1", config.bindAddress)
|
||||||
|
assertNotNull(config.authenticator)
|
||||||
|
assertTrue(config.authenticator!!.checkCredentials("username", "password"))
|
||||||
|
|
||||||
|
val defaultValueConfig = MetricsConfig()
|
||||||
|
val defaultValueJson = gson.toJsonTree(defaultValueConfig).asJsonObject
|
||||||
|
assertEquals(defaultValueConfig.enable, defaultValueJson.get("enable").asBoolean)
|
||||||
|
assertEquals(defaultValueConfig.port, defaultValueJson.get("port").asInt)
|
||||||
|
assertEquals(defaultValueConfig.bindAddress, defaultValueJson.get("bindAddress").asString)
|
||||||
|
assertNull(defaultValueJson.get("authenticator"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserializer - default value`() {
|
||||||
|
val actualConfig = gson.fromJson("{}", MetricsConfig::class.java)
|
||||||
|
val expectConfig = MetricsConfig()
|
||||||
|
|
||||||
|
assertEquals(expectConfig, actualConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MavenRepositoryConfigTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(MavenRepositoryConfig::class.java, MavenRepositoryConfigSerializer)
|
||||||
|
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serializer`() {
|
||||||
|
val config = MavenRepositoryConfig(
|
||||||
|
id = "test",
|
||||||
|
url = URL("http://localhost:8080/repository"),
|
||||||
|
proxy = Proxy(
|
||||||
|
"http",
|
||||||
|
"localhost",
|
||||||
|
8080,
|
||||||
|
),
|
||||||
|
layout = "legacy",
|
||||||
|
enableReleases = false,
|
||||||
|
enableSnapshots = true,
|
||||||
|
authentication = null
|
||||||
|
)
|
||||||
|
val json = gson.toJsonTree(config).asJsonObject
|
||||||
|
assertEquals(config.id, json.get("id").asString)
|
||||||
|
assertEquals(config.url.toString(), json.get("url").asString)
|
||||||
|
|
||||||
|
assertEquals(config.proxy!!.host, json.get("proxy").asJsonObject.get("host").asString)
|
||||||
|
assertEquals(config.proxy!!.port, json.get("proxy").asJsonObject.get("port").asInt)
|
||||||
|
assertEquals(config.proxy!!.type, json.get("proxy").asJsonObject.get("type").asString)
|
||||||
|
|
||||||
|
assertEquals(config.layout, json.get("layout").asString)
|
||||||
|
assertEquals(config.enableReleases, json.get("enableReleases").asBoolean)
|
||||||
|
assertEquals(config.enableSnapshots, json.get("enableSnapshots").asBoolean)
|
||||||
|
assertNull(json.get("authentication"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserializer`() {
|
||||||
|
@Language("JSON5")
|
||||||
|
val json = """
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
"url": "http://localhost:8080/repository",
|
||||||
|
"proxy": {
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 8080,
|
||||||
|
"type": "HTTP"
|
||||||
|
},
|
||||||
|
"layout": "legacy",
|
||||||
|
"enableReleases": false,
|
||||||
|
"enableSnapshots": true,
|
||||||
|
"authentication": {
|
||||||
|
"username": "testUser",
|
||||||
|
"password": "testPassword"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val config = gson.fromJson(json, MavenRepositoryConfig::class.java)
|
||||||
|
|
||||||
|
assertEquals("test", config.id)
|
||||||
|
assertEquals(URL("http://localhost:8080/repository"), config.url)
|
||||||
|
assertEquals(
|
||||||
|
Proxy(
|
||||||
|
"HTTP",
|
||||||
|
"localhost",
|
||||||
|
8080
|
||||||
|
), config.proxy
|
||||||
|
)
|
||||||
|
assertEquals("legacy", config.layout)
|
||||||
|
assertEquals(false, config.enableReleases)
|
||||||
|
assertEquals(true, config.enableSnapshots)
|
||||||
|
assertNotNull(config.authentication)
|
||||||
|
|
||||||
|
val authContext = mockk<AuthenticationContext> {
|
||||||
|
every { put(ofType(String::class), any()) } answers { }
|
||||||
|
}
|
||||||
|
config.authentication!!.fill(authContext, null, emptyMap())
|
||||||
|
|
||||||
|
verify {
|
||||||
|
authContext.put(any(), "testUser")
|
||||||
|
authContext.put(any(), "testPassword".toCharArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class AppConfigTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
|
.registerTypeAdapter(ProxyConfig::class.java, ProxyConfigSerializer)
|
||||||
|
.registerTypeAdapter(UsernameAuthenticator::class.java, UsernameAuthenticatorSerializer)
|
||||||
|
.registerTypeAdapter(MavenRepositoryConfig::class.java, MavenRepositoryConfigSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serializer - default value`() {
|
||||||
|
val config = AppConfig()
|
||||||
|
val json = gson.toJsonTree(config).asJsonObject
|
||||||
|
assertEquals(config.proxy.type.name, json.get("proxy").asJsonObject.get("type").asString)
|
||||||
|
assertEquals(config.proxy.host, json.get("proxy").asJsonObject.get("host").asString)
|
||||||
|
assertEquals(config.proxy.port, json.get("proxy").asJsonObject.get("port").asInt)
|
||||||
|
assertEquals(config.metrics.enable, json.get("metrics").asJsonObject.get("enable").asBoolean)
|
||||||
|
assertEquals(config.metrics.port, json.get("metrics").asJsonObject.get("port").asInt)
|
||||||
|
assertEquals(config.metrics.bindAddress, json.get("metrics").asJsonObject.get("bindAddress").asString)
|
||||||
|
assertNull(json["metrics"].asJsonObject.get("authenticator"))
|
||||||
|
assertTrue(json["mavenRepositories"].asJsonArray.isEmpty)
|
||||||
|
assertNull(json["mavenLocalRepository"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json serializer - Provide values`() {
|
||||||
|
val config = AppConfig(
|
||||||
|
proxy = ProxyConfig(
|
||||||
|
type = ProxyType.HTTP,
|
||||||
|
host = "localhost",
|
||||||
|
port = 8080
|
||||||
|
),
|
||||||
|
metrics = MetricsConfig(
|
||||||
|
enable = true,
|
||||||
|
port = 8800,
|
||||||
|
bindAddress = "127.0.0.1",
|
||||||
|
authenticator = UsernameAuthenticator(
|
||||||
|
username = "username",
|
||||||
|
password = "password"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
mavenRepositories = listOf(
|
||||||
|
MavenRepositoryConfig(
|
||||||
|
url = URL("https://repository.maven.apache.org/maven2/")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
mavenLocalRepository = "file:///tmp/maven-local-repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = gson.toJsonTree(config).asJsonObject
|
||||||
|
|
||||||
|
assertEquals(config.proxy.type.name, json.get("proxy").asJsonObject.get("type").asString)
|
||||||
|
assertEquals(config.proxy.host, json.get("proxy").asJsonObject.get("host").asString)
|
||||||
|
assertEquals(config.proxy.port, json.get("proxy").asJsonObject.get("port").asInt)
|
||||||
|
|
||||||
|
assertEquals(config.metrics.enable, json.get("metrics").asJsonObject.get("enable").asBoolean)
|
||||||
|
assertEquals(config.metrics.port, json.get("metrics").asJsonObject.get("port").asInt)
|
||||||
|
assertEquals(config.metrics.bindAddress, json.get("metrics").asJsonObject.get("bindAddress").asString)
|
||||||
|
assertNotNull(config.metrics.authenticator)
|
||||||
|
assertTrue(
|
||||||
|
config.metrics.authenticator!!.checkCredentials(
|
||||||
|
json.get("metrics").asJsonObject.get("authenticator").asJsonObject.get("username").asString,
|
||||||
|
json.get("metrics").asJsonObject.get("authenticator").asJsonObject.get("password").asString
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(1, json["mavenRepositories"].asJsonArray.size())
|
||||||
|
assertEquals(
|
||||||
|
config.mavenRepositories[0].url.toString(),
|
||||||
|
json["mavenRepositories"].asJsonArray[0].asJsonObject.get("url").asString
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(config.mavenLocalRepository, json["mavenLocalRepository"].asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserializer - complete`() {
|
||||||
|
val json = """
|
||||||
|
{
|
||||||
|
"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 config = gson.fromJson(json, AppConfig::class.java)
|
||||||
|
|
||||||
|
assertEquals(ProxyType.HTTP, config.proxy.type)
|
||||||
|
assertEquals("localhost", config.proxy.host)
|
||||||
|
assertEquals(8080, config.proxy.port)
|
||||||
|
|
||||||
|
assertEquals(true, config.metrics.enable)
|
||||||
|
assertEquals(8800, config.metrics.port)
|
||||||
|
assertEquals("127.0.0.1", config.metrics.bindAddress)
|
||||||
|
assertNotNull(config.metrics.authenticator)
|
||||||
|
assertTrue(config.metrics.authenticator!!.checkCredentials("username", "password"))
|
||||||
|
|
||||||
|
assertEquals(1, config.mavenRepositories.size)
|
||||||
|
assertEquals(URL("https://repository.maven.apache.org/maven2/"), config.mavenRepositories[0].url)
|
||||||
|
|
||||||
|
assertEquals("file:///tmp/maven-local-repository", config.mavenLocalRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json deserializer - default value`() {
|
||||||
|
val actualConfig = gson.fromJson("{}", AppConfig::class.java)
|
||||||
|
val expectConfig = AppConfig()
|
||||||
|
|
||||||
|
assertEquals(expectConfig, actualConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
scalabot-meta/src/test/kotlin/UsernameAuthenticatorTest.kt
Normal file
38
scalabot-meta/src/test/kotlin/UsernameAuthenticatorTest.kt
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package net.lamgc.scalabot.config
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
internal class UsernameAuthenticatorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkCredentialsTest() {
|
||||||
|
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||||
|
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
||||||
|
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
||||||
|
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
||||||
|
assertFalse(authenticator.checkCredentials("falseUser", "falsePassword"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toJsonObjectTest() {
|
||||||
|
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||||
|
val jsonObject = authenticator.toJsonObject()
|
||||||
|
assertEquals("testUser", jsonObject["username"]?.asString)
|
||||||
|
assertEquals("testPassword", jsonObject["password"]?.asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun equalsTest() {
|
||||||
|
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||||
|
assertEquals(authenticator, UsernameAuthenticator("testUser", "testPassword"))
|
||||||
|
assertEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "testPassword").hashCode())
|
||||||
|
assertNotEquals(authenticator, UsernameAuthenticator("testUser", "falsePassword"))
|
||||||
|
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("testUser", "falsePassword").hashCode())
|
||||||
|
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "testPassword"))
|
||||||
|
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "testPassword").hashCode())
|
||||||
|
assertNotEquals(authenticator, UsernameAuthenticator("falseUser", "falsePassword"))
|
||||||
|
assertNotEquals(authenticator.hashCode(), UsernameAuthenticator("falseUser", "falsePassword").hashCode())
|
||||||
|
assertFalse(authenticator.equals(null))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
708
scalabot-meta/src/test/kotlin/serializer/SerializersKtTest.kt
Normal file
708
scalabot-meta/src/test/kotlin/serializer/SerializersKtTest.kt
Normal file
@ -0,0 +1,708 @@
|
|||||||
|
package net.lamgc.scalabot.config.serializer
|
||||||
|
|
||||||
|
import com.google.gson.*
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import net.lamgc.scalabot.config.*
|
||||||
|
import org.eclipse.aether.artifact.Artifact
|
||||||
|
import org.eclipse.aether.artifact.DefaultArtifact
|
||||||
|
import org.eclipse.aether.repository.Authentication
|
||||||
|
import org.eclipse.aether.repository.AuthenticationContext
|
||||||
|
import org.eclipse.aether.repository.Proxy
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
import java.net.URL
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
internal class SerializersKtTest {
|
||||||
|
|
||||||
|
private val instance: Any
|
||||||
|
private val method: Method
|
||||||
|
|
||||||
|
init {
|
||||||
|
val clazz = Class.forName("net.lamgc.scalabot.config.serializer.SerializerUtils")
|
||||||
|
method = clazz.getDeclaredMethod("checkJsonKey", JsonObject::class.java, String::class.java)
|
||||||
|
method.isAccessible = true
|
||||||
|
instance = clazz.getDeclaredField("INSTANCE").apply {
|
||||||
|
isAccessible = true
|
||||||
|
}.get(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invoke(json: JsonObject, key: String): String {
|
||||||
|
try {
|
||||||
|
return method.invoke(instance, json, key) as String
|
||||||
|
} catch (e: InvocationTargetException) {
|
||||||
|
throw e.targetException
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Json key checker test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
invoke(JsonObject(), "NOT_EXIST_KEY")
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
invoke(JsonObject().apply { add("NULL_KEY", JsonNull.INSTANCE) }, "NULL_KEY")
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
invoke(JsonObject().apply { add("ARRAY_KEY", JsonArray()) }, "ARRAY_KEY")
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
invoke(JsonObject().apply { add("OBJECT_KEY", JsonObject()) }, "OBJECT_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
val expectKey = "TEST"
|
||||||
|
val expectString = "testString"
|
||||||
|
val json = JsonObject().apply { addProperty(expectKey, expectString) }
|
||||||
|
|
||||||
|
assertEquals(expectString, invoke(json, expectKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ProxyTypeSerializerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `serialize test`() {
|
||||||
|
for (type in ProxyType.values()) {
|
||||||
|
assertEquals(
|
||||||
|
JsonPrimitive(type.name), ProxyTypeSerializer.serialize(type, null, null),
|
||||||
|
"ProxyType 序列化结果与预期不符."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deserialize test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyTypeSerializer.deserialize(JsonObject(), null, null)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyTypeSerializer.deserialize(JsonArray(), null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyTypeSerializer.deserialize(JsonPrimitive("NOT_IN_ENUM_VALUE"), null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
ProxyType.NO_PROXY,
|
||||||
|
ProxyTypeSerializer.deserialize(JsonNull.INSTANCE, null, null)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (type in ProxyType.values()) {
|
||||||
|
assertEquals(
|
||||||
|
type, ProxyTypeSerializer.deserialize(JsonPrimitive(type.name), null, null),
|
||||||
|
"ProxyType 反序列化结果与预期不符."
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
type, ProxyTypeSerializer.deserialize(JsonPrimitive(" ${type.name} "), null, null),
|
||||||
|
"ProxyType 反序列化时未对 Json 字符串进行修剪(trim)."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MavenRepositoryConfigSerializerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unsupported json type deserialize test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
JsonArray(),
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
JsonNull.INSTANCE,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json primitive deserialize test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
JsonPrimitive("NOT A URL."),
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val expectRepoUrl = "https://repo.example.org/maven"
|
||||||
|
val config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
JsonPrimitive(expectRepoUrl),
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNull(config.id)
|
||||||
|
assertEquals(URL(expectRepoUrl), config.url)
|
||||||
|
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
||||||
|
assertEquals("default", config.layout)
|
||||||
|
assertTrue(config.enableReleases)
|
||||||
|
assertTrue(config.enableSnapshots)
|
||||||
|
assertNull(config.authentication)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json object default deserialize test`() {
|
||||||
|
val expectRepoUrl = "https://repo.example.org/maven"
|
||||||
|
val jsonObject = JsonObject()
|
||||||
|
jsonObject.addProperty("url", expectRepoUrl)
|
||||||
|
val config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNull(config.id)
|
||||||
|
assertEquals(URL(expectRepoUrl), config.url)
|
||||||
|
assertNull(config.proxy, "Proxy 默认值不为 null.")
|
||||||
|
assertEquals("default", config.layout)
|
||||||
|
assertTrue(config.enableReleases)
|
||||||
|
assertTrue(config.enableSnapshots)
|
||||||
|
assertNull(config.authentication)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `json object deserialize test`() {
|
||||||
|
@Language("JSON5")
|
||||||
|
val looksGoodJsonString = """
|
||||||
|
{
|
||||||
|
"id": "test-repository",
|
||||||
|
"url": "https://repo.example.org/maven",
|
||||||
|
"proxy": {
|
||||||
|
"type": "http",
|
||||||
|
"host": "127.0.1.1",
|
||||||
|
"port": 10800
|
||||||
|
},
|
||||||
|
"layout": "default",
|
||||||
|
"enableReleases": false,
|
||||||
|
"enableSnapshots": true
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val jsonObject = Gson().fromJson(looksGoodJsonString, JsonObject::class.java)
|
||||||
|
var config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(jsonObject["id"].asString, config.id)
|
||||||
|
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||||
|
assertEquals(Proxy("http", "127.0.1.1", 10800), config.proxy)
|
||||||
|
assertEquals(jsonObject["layout"].asString, config.layout)
|
||||||
|
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||||
|
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
jsonObject.add("proxy", JsonNull.INSTANCE)
|
||||||
|
jsonObject.remove("layout")
|
||||||
|
|
||||||
|
config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(jsonObject["id"].asString, config.id)
|
||||||
|
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||||
|
assertNull(config.proxy)
|
||||||
|
assertEquals("default", config.layout)
|
||||||
|
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||||
|
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
jsonObject.add("layout", mockk<JsonPrimitive> {
|
||||||
|
every { asString }.returns(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(jsonObject["id"].asString, config.id)
|
||||||
|
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||||
|
assertNull(config.proxy)
|
||||||
|
assertEquals("default", config.layout)
|
||||||
|
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||||
|
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||||
|
assertNull(config.authentication)
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
jsonObject.add("authentication", JsonObject().apply {
|
||||||
|
addProperty("username", "testUsername")
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
})
|
||||||
|
|
||||||
|
config = MavenRepositoryConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
MavenRepositoryConfig::class.java,
|
||||||
|
TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(jsonObject["id"].asString, config.id)
|
||||||
|
assertEquals(URL(jsonObject["url"].asString), config.url)
|
||||||
|
assertNull(config.proxy)
|
||||||
|
assertEquals("default", config.layout)
|
||||||
|
assertEquals(jsonObject["enableReleases"].asBoolean, config.enableReleases)
|
||||||
|
assertEquals(jsonObject["enableSnapshots"].asBoolean, config.enableSnapshots)
|
||||||
|
assertNotNull(config.authentication)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestJsonSerializationContext(private val gson: Gson) : JsonDeserializationContext,
|
||||||
|
JsonSerializationContext {
|
||||||
|
|
||||||
|
override fun <T : Any?> deserialize(json: JsonElement?, typeOfT: Type): T {
|
||||||
|
return gson.fromJson(json, typeOfT)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun default(): TestJsonSerializationContext {
|
||||||
|
return TestJsonSerializationContext(
|
||||||
|
GsonBuilder()
|
||||||
|
.registerTypeAdapter(MavenRepositoryConfig::class.java, MavenRepositoryConfigSerializer)
|
||||||
|
.registerTypeAdapter(BotConfig::class.java, BotConfigSerializer)
|
||||||
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
|
.registerTypeAdapter(Artifact::class.java, ArtifactSerializer)
|
||||||
|
.registerTypeAdapter(Authentication::class.java, AuthenticationSerializer)
|
||||||
|
.registerTypeAdapter(UsernameAuthenticator::class.java, UsernameAuthenticatorSerializer)
|
||||||
|
.registerTypeAdapter(ProxyConfig::class.java, ProxyConfigSerializer)
|
||||||
|
.create()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(src: Any?): JsonElement {
|
||||||
|
return gson.toJsonTree(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(src: Any?, typeOfSrc: Type?): JsonElement {
|
||||||
|
return gson.toJsonTree(src, typeOfSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class AuthenticationSerializerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deserialize test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
AuthenticationSerializer.deserialize(
|
||||||
|
JsonNull.INSTANCE,
|
||||||
|
Authentication::class.java, TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
AuthenticationSerializer.deserialize(
|
||||||
|
JsonArray(),
|
||||||
|
Authentication::class.java, TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
AuthenticationSerializer.deserialize(
|
||||||
|
JsonPrimitive("A STRING"),
|
||||||
|
Authentication::class.java, TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val expectJsonObject = JsonObject().apply {
|
||||||
|
addProperty("username", "testUsername")
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
}
|
||||||
|
|
||||||
|
val mockContext = mockk<AuthenticationContext> {
|
||||||
|
every { put(any(), any()) }.answers { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = AuthenticationSerializer.deserialize(
|
||||||
|
expectJsonObject,
|
||||||
|
Authentication::class.java, TestJsonSerializationContext.default()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNotNull(result)
|
||||||
|
result.fill(mockContext, "username", null)
|
||||||
|
result.fill(mockContext, "password", null)
|
||||||
|
|
||||||
|
verify {
|
||||||
|
mockContext.put("username", "testUsername")
|
||||||
|
mockContext.put("password", "testPassword".toCharArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BotConfigSerializerTest {
|
||||||
|
|
||||||
|
private val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(BotConfig::class.java, BotConfigSerializer)
|
||||||
|
.registerTypeAdapter(Artifact::class.java, ArtifactSerializer)
|
||||||
|
.registerTypeAdapter(ProxyType::class.java, ProxyTypeSerializer)
|
||||||
|
.registerTypeAdapter(ProxyConfig::class.java, ProxyConfigSerializer)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `serializer test`() {
|
||||||
|
// 检查 BotConfig 的序列化
|
||||||
|
val botConfig = BotConfig(
|
||||||
|
account = BotAccount(
|
||||||
|
name = "test-bot",
|
||||||
|
token = "test-token",
|
||||||
|
creatorId = 10000
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 使用 gson 序列化 botConfig, 并检查序列化结果
|
||||||
|
val jsonObject = gson.toJsonTree(botConfig) as JsonObject
|
||||||
|
assertEquals("test-bot", jsonObject["account"].asJsonObject["name"].asString)
|
||||||
|
assertEquals("test-token", jsonObject["account"].asJsonObject["token"].asString)
|
||||||
|
assertEquals(10000, jsonObject["account"].asJsonObject["creatorId"].asInt)
|
||||||
|
|
||||||
|
assertEquals(botConfig.enabled, jsonObject["enabled"].asBoolean)
|
||||||
|
assertEquals(botConfig.proxy.host, jsonObject["proxy"].asJsonObject["host"].asString)
|
||||||
|
assertEquals(botConfig.proxy.port, jsonObject["proxy"].asJsonObject["port"].asInt)
|
||||||
|
assertEquals(botConfig.proxy.type.name, jsonObject["proxy"].asJsonObject["type"].asString)
|
||||||
|
assertEquals(botConfig.disableBuiltInAbility, jsonObject["disableBuiltInAbility"].asBoolean)
|
||||||
|
assertEquals(botConfig.autoUpdateCommandList, jsonObject["autoUpdateCommandList"].asBoolean)
|
||||||
|
assertEquals(botConfig.extensions.isEmpty(), jsonObject["extensions"].asJsonArray.isEmpty)
|
||||||
|
assertEquals(botConfig.baseApiUrl, jsonObject["baseApiUrl"].asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deserialize test`() {
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonNull.INSTANCE,
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonArray(),
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonPrimitive("A STRING"),
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 BotConfig 的反序列化中是否能正确判断 account 的类型
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonObject().apply {
|
||||||
|
addProperty("account", "A STRING")
|
||||||
|
},
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonObject().apply {
|
||||||
|
add("account", JsonNull.INSTANCE)
|
||||||
|
},
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonObject().apply {
|
||||||
|
add("account", JsonArray())
|
||||||
|
},
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
BotConfigSerializer.deserialize(
|
||||||
|
JsonObject(),
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val expectBotAccount = BotAccount(
|
||||||
|
name = "test-bot",
|
||||||
|
token = "test-token",
|
||||||
|
creatorId = 10000
|
||||||
|
)
|
||||||
|
val expectDefaultBotConfig = BotConfig(account = expectBotAccount)
|
||||||
|
val minimumJsonObject = JsonObject().apply {
|
||||||
|
add("account", gson.toJsonTree(expectBotAccount))
|
||||||
|
}
|
||||||
|
val actualMinimumBotConfig = BotConfigSerializer.deserialize(
|
||||||
|
minimumJsonObject, BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
assertNotNull(actualMinimumBotConfig)
|
||||||
|
assertEquals(expectDefaultBotConfig, actualMinimumBotConfig)
|
||||||
|
|
||||||
|
val expectDefaultProxy = ProxyConfig(
|
||||||
|
type = ProxyType.HTTP,
|
||||||
|
host = "https://example.com",
|
||||||
|
port = 443
|
||||||
|
)
|
||||||
|
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
val jsonObject = JsonObject().apply {
|
||||||
|
add(
|
||||||
|
"account", gson.toJsonTree(
|
||||||
|
BotAccount(
|
||||||
|
name = "test-bot",
|
||||||
|
token = "test-token",
|
||||||
|
creatorId = 10000
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
addProperty("enabled", true)
|
||||||
|
add("proxy", gson.toJsonTree(expectDefaultProxy))
|
||||||
|
addProperty("disableBuiltInAbility", true)
|
||||||
|
addProperty("autoUpdateCommandList", true)
|
||||||
|
addProperty("baseApiUrl", "https://test.com")
|
||||||
|
add("extensions", JsonArray().apply {
|
||||||
|
add("org.example:test:1.0.0-SNAPSHOT")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
val botConfig = BotConfigSerializer.deserialize(
|
||||||
|
jsonObject,
|
||||||
|
BotConfig::class.java, TestJsonSerializationContext(gson)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals("test-bot", botConfig.account.name)
|
||||||
|
assertEquals("test-token", botConfig.account.token)
|
||||||
|
assertEquals(10000, botConfig.account.creatorId)
|
||||||
|
assertEquals(true, botConfig.enabled)
|
||||||
|
assertEquals(expectDefaultProxy, botConfig.proxy)
|
||||||
|
assertEquals(true, botConfig.disableBuiltInAbility)
|
||||||
|
assertEquals(true, botConfig.autoUpdateCommandList)
|
||||||
|
assertEquals("https://test.com", botConfig.baseApiUrl)
|
||||||
|
assertEquals(false, botConfig.extensions.isEmpty())
|
||||||
|
assertEquals(1, botConfig.extensions.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ProxyConfigSerializerTest {
|
||||||
|
|
||||||
|
// 测试 ProxyConfig 的 Json 序列化
|
||||||
|
@Test
|
||||||
|
fun `serialize test`() {
|
||||||
|
assertEquals(JsonNull.INSTANCE, ProxyConfigSerializer.serialize(null, null, null))
|
||||||
|
|
||||||
|
val expectDefaultConfig = ProxyConfig()
|
||||||
|
val actualDefaultJson = ProxyConfigSerializer.serialize(expectDefaultConfig, null, null)
|
||||||
|
assertTrue(actualDefaultJson is JsonObject)
|
||||||
|
assertEquals(expectDefaultConfig.type.name, actualDefaultJson["type"].asString)
|
||||||
|
assertEquals(expectDefaultConfig.host, actualDefaultJson["host"].asString)
|
||||||
|
assertEquals(expectDefaultConfig.port, actualDefaultJson["port"].asInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Bad type deserialize test`() {
|
||||||
|
val defaultConfig = ProxyConfig()
|
||||||
|
assertEquals(defaultConfig, ProxyConfigSerializer.deserialize(null, null, null))
|
||||||
|
assertEquals(defaultConfig, ProxyConfigSerializer.deserialize(JsonNull.INSTANCE, null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deserialize test - object`() {
|
||||||
|
val defaultConfig = ProxyConfig()
|
||||||
|
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyConfigSerializer.deserialize(JsonArray(), null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val jsonWithoutType = JsonObject().apply {
|
||||||
|
addProperty("host", "example.com")
|
||||||
|
addProperty("port", 8080)
|
||||||
|
}
|
||||||
|
assertEquals(defaultConfig, ProxyConfigSerializer.deserialize(jsonWithoutType, null, null))
|
||||||
|
|
||||||
|
val looksGoodJson = JsonObject().apply {
|
||||||
|
addProperty("type", "HTTP")
|
||||||
|
addProperty("host", "example.com")
|
||||||
|
addProperty("port", 8080)
|
||||||
|
}
|
||||||
|
assertEquals(
|
||||||
|
ProxyConfig(
|
||||||
|
type = ProxyType.HTTP,
|
||||||
|
host = "example.com",
|
||||||
|
port = 8080
|
||||||
|
), ProxyConfigSerializer.deserialize(looksGoodJson, null, null)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyConfigSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("type", "UNKNOWN")
|
||||||
|
addProperty("host", "example.com")
|
||||||
|
addProperty("port", 8080)
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyConfigSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("type", "HTTP")
|
||||||
|
addProperty("host", "example.com")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
assertThrows(JsonParseException::class.java) {
|
||||||
|
ProxyConfigSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("type", "HTTP")
|
||||||
|
addProperty("port", 8080)
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ArtifactSerializerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun badJsonType() {
|
||||||
|
assertFailsWith<JsonParseException> { ArtifactSerializer.deserialize(JsonObject(), null, null) }
|
||||||
|
assertFailsWith<JsonParseException> { ArtifactSerializer.deserialize(JsonArray(), null, null) }
|
||||||
|
assertFailsWith<JsonParseException> { ArtifactSerializer.deserialize(JsonPrimitive("A STRING"), null, null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Basic format serialization`() {
|
||||||
|
val gav = "org.example.software:test:1.0.0-SNAPSHOT"
|
||||||
|
val expectArtifact = DefaultArtifact(gav)
|
||||||
|
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
||||||
|
assertEquals(expectArtifact, actualArtifact)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Full format serialization`() {
|
||||||
|
val gav = "org.example.software:test:war:javadoc:1.0.0-SNAPSHOT"
|
||||||
|
val expectArtifact = DefaultArtifact(gav)
|
||||||
|
val actualArtifact = DefaultArtifact(ArtifactSerializer.serialize(expectArtifact, null, null).asString)
|
||||||
|
assertEquals(expectArtifact, actualArtifact)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Bad format serialization`() {
|
||||||
|
assertFailsWith<JsonParseException> {
|
||||||
|
ArtifactSerializer.deserialize(JsonPrimitive("org.example~test"), null, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Other artifact implementation serialization`() {
|
||||||
|
val gav = "org.example.software:test:war:javadoc:1.0.0-SNAPSHOT"
|
||||||
|
val expectArtifact = DefaultArtifact(gav)
|
||||||
|
val otherArtifactImpl = mockk<Artifact> {
|
||||||
|
every { groupId } returns expectArtifact.groupId
|
||||||
|
every { artifactId } returns expectArtifact.artifactId
|
||||||
|
every { version } returns expectArtifact.version
|
||||||
|
every { classifier } returns expectArtifact.classifier
|
||||||
|
every { extension } returns expectArtifact.extension
|
||||||
|
}
|
||||||
|
|
||||||
|
val json = ArtifactSerializer.serialize(otherArtifactImpl, null, null)
|
||||||
|
assertTrue(json is JsonPrimitive)
|
||||||
|
assertEquals(expectArtifact.toString(), json.asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deserialize() {
|
||||||
|
val gav = "org.example.software:test:war:javadoc:1.0.0-SNAPSHOT"
|
||||||
|
val expectArtifact = DefaultArtifact(gav)
|
||||||
|
val actualArtifact = ArtifactSerializer.deserialize(JsonPrimitive(gav), null, null)
|
||||||
|
assertEquals(expectArtifact, actualArtifact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UsernameAuthenticatorSerializerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun serializeTest() {
|
||||||
|
val authenticator = UsernameAuthenticator("testUser", "testPassword")
|
||||||
|
val jsonElement = UsernameAuthenticatorSerializer.serialize(authenticator, null, null)
|
||||||
|
assertTrue(jsonElement.isJsonObject)
|
||||||
|
val jsonObject = jsonElement.asJsonObject
|
||||||
|
assertEquals("testUser", jsonObject["username"]?.asString)
|
||||||
|
assertEquals("testPassword", jsonObject["password"]?.asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deserializeTest() {
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonArray(), null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonPrimitive(""), null, null)
|
||||||
|
}
|
||||||
|
assertNull(UsernameAuthenticatorSerializer.deserialize(JsonNull.INSTANCE, null, null))
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "testUser")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "testUser")
|
||||||
|
add("password", JsonArray())
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
add("username", JsonArray())
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "")
|
||||||
|
addProperty("password", "")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "testUser")
|
||||||
|
addProperty("password", "")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
org.junit.jupiter.api.assertThrows<JsonParseException> {
|
||||||
|
UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "")
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
}, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val authenticator = UsernameAuthenticatorSerializer.deserialize(JsonObject().apply {
|
||||||
|
addProperty("username", "testUser")
|
||||||
|
addProperty("password", "testPassword")
|
||||||
|
}, null, null)
|
||||||
|
assertNotNull(authenticator)
|
||||||
|
|
||||||
|
assertTrue(authenticator.checkCredentials("testUser", "testPassword"))
|
||||||
|
assertFalse(authenticator.checkCredentials("falseUser", "testPassword"))
|
||||||
|
assertFalse(authenticator.checkCredentials("testUser", "falsePassword"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,3 +4,4 @@ rootProject.name = "scalabot"
|
|||||||
include(":scalabot-app")
|
include(":scalabot-app")
|
||||||
include(":scalabot-extension")
|
include(":scalabot-extension")
|
||||||
include("scalabot-ext-example")
|
include("scalabot-ext-example")
|
||||||
|
include("scalabot-meta")
|
||||||
|
Loading…
Reference in New Issue
Block a user