135 lines
5.3 KiB
Kotlin
135 lines
5.3 KiB
Kotlin
package me.him188.ani.datasources.api.test.codegen
|
||
|
||
import com.squareup.kotlinpoet.AnnotationSpec
|
||
import com.squareup.kotlinpoet.ClassName
|
||
import com.squareup.kotlinpoet.FileSpec
|
||
import com.squareup.kotlinpoet.FunSpec
|
||
import com.squareup.kotlinpoet.TypeSpec
|
||
import kotlinx.serialization.json.Json
|
||
import me.him188.ani.datasources.api.test.codegen.main.TestData
|
||
import me.him188.ani.datasources.api.topic.Topic
|
||
import me.him188.ani.datasources.api.topic.titles.ParsedTopicTitle
|
||
import me.him188.ani.datasources.api.topic.titles.RawTitleParser
|
||
import me.him188.ani.datasources.api.topic.titles.parse
|
||
|
||
val json = Json {
|
||
ignoreUnknownKeys = true
|
||
prettyPrint = true
|
||
}
|
||
|
||
class TopicSet(
|
||
val topics: List<Topic>,
|
||
)
|
||
|
||
class TestSuite(
|
||
val originalName: String,
|
||
val dataSource: String,
|
||
val name: String,
|
||
val cases: List<TestCase>
|
||
)
|
||
|
||
class TestCase(
|
||
val name: String,
|
||
val title: String,
|
||
val parsed: ParsedTopicTitle,
|
||
)
|
||
|
||
class TestGenerator(
|
||
private val parser: RawTitleParser
|
||
) {
|
||
fun createSuite(testData: TestData): TestSuite {
|
||
fun String.sanitize() = replace("%", "_")
|
||
.replace(".", "_")
|
||
.replace("-", "_")
|
||
.replace("!", "_")
|
||
.replace("!", "_")
|
||
.replace("~", "_")
|
||
|
||
return TestSuite(
|
||
originalName = testData.originalName.sanitize(),
|
||
name = testData.kotlinClassName.sanitize(),
|
||
dataSource = testData.dataSource,
|
||
cases = testData.topics.map {
|
||
TestCase(
|
||
name = it.id.removeSuffix(".html").sanitize(),
|
||
title = it.rawTitle,
|
||
parsed = parser.parse(it.rawTitle),
|
||
)
|
||
},
|
||
)
|
||
}
|
||
|
||
// 这库真是各种难用
|
||
fun generateSuite(suite: TestSuite): FileSpec = FileSpec.builder(
|
||
"", // 他会创建目录层级
|
||
"PatternTitleParserTest${suite.name}",
|
||
).apply {
|
||
addAnnotation(
|
||
AnnotationSpec.builder(ClassName.bestGuess("Suppress")).apply {
|
||
addMember("\"FunctionName\"")
|
||
addMember("\"ClassName\"")
|
||
addMember("\"RedundantVisibilityModifier\"")
|
||
addMember("\"PackageDirectoryMismatch\"")
|
||
addMember("\"NonAsciiCharacters\"")
|
||
addMember("\"SpellCheckingInspection\"")
|
||
}.build(),
|
||
)
|
||
addImport("me.him188.ani.datasources.api.title", "PatternBasedTitleParserTestSuite")
|
||
addImport("kotlin.test", "assertEquals") // 它不允许 "*"
|
||
addImport("me.him188.ani.datasources.api", "SubtitleKind") // 它不允许 "*"
|
||
addType(
|
||
TypeSpec.classBuilder(
|
||
ClassName(
|
||
"me.him188.ani.datasources.api.title.generated", // 这库并不会写出 package
|
||
"PatternTitleParserTest${suite.name}",
|
||
),
|
||
).apply {
|
||
addKdoc(
|
||
"""
|
||
原名: `${suite.originalName}`
|
||
数据源: `${suite.dataSource}`
|
||
|
||
由 `test-codegen` 的 `GenerateTests.kt` 生成, 不要手动修改!
|
||
如果你优化了解析器, 这些 test 可能会失败, 请检查是否它是因为以前解析错误而现在解析正确了.
|
||
如果是, 请更新测试数据: 执行 `GenerateTests.kt`.
|
||
""".trimIndent(),
|
||
)
|
||
superclass(ClassName("me.him188.ani.datasources.api.title", "PatternBasedTitleParserTestSuite"))
|
||
for (case in suite.cases) case.parsed.run {
|
||
addFunction(
|
||
FunSpec.builder(case.name)
|
||
.addAnnotation(ClassName.bestGuess("kotlin.test.Test"))
|
||
// 这库会自动 wrap code, 如果不写 %S 就可能出问题
|
||
// 他不会自动换行, 必须要有 + "\n"
|
||
.addCode(
|
||
"""val r = parse(%S)""" + "\n", case.title,
|
||
)
|
||
.addCode("assertEquals(%S, r.episodeRange.toString())" + "\n", episodeRange.toString())
|
||
.addCode(
|
||
"assertEquals(%S, r.subtitleLanguages.sortedBy { it.id }.joinToString { it.id })" + "\n",
|
||
subtitleLanguages.sortedBy { it.id }.joinToString { it.id },
|
||
)
|
||
.addCode(
|
||
"assertEquals(%S, r.resolution.toString())" + "\n",
|
||
resolution.toString(),
|
||
)
|
||
.run {
|
||
if (subtitleKind == null) {
|
||
addCode("assertEquals(null, r.subtitleKind)" + "\n")
|
||
} else {
|
||
addCode(
|
||
"assertEquals(SubtitleKind.%L, r.subtitleKind)" + "\n",
|
||
subtitleKind,
|
||
)
|
||
}
|
||
}
|
||
.build(),
|
||
)
|
||
}
|
||
}.build(),
|
||
)
|
||
}.build()
|
||
}
|
||
|
||
private const val Q = "\"\"\""
|