diff --git a/src/test/kotlin/test/ReproduceIssueTest.kt b/src/test/kotlin/test/ReproduceIssueTest.kt index dc919038..1582e670 100644 --- a/src/test/kotlin/test/ReproduceIssueTest.kt +++ b/src/test/kotlin/test/ReproduceIssueTest.kt @@ -1,6 +1,6 @@ package test -import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.JsonNode import ext.JACKSON import icu.samnyan.aqua.net.games.chu3.Chu3DataExport import icu.samnyan.aqua.net.games.mai2.Maimai2DataExport @@ -15,11 +15,8 @@ import icu.samnyan.aqua.sega.ongeki.model.UserPlaylog as OngekiUserPlaylog import icu.samnyan.aqua.sega.util.BASIC_MAPPER import icu.samnyan.aqua.sega.util.STRING_MAPPER import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test -import tools.jackson.databind.json.JsonMapper -import tools.jackson.module.kotlin.KotlinModule class ReproduceIssueTest { @@ -28,8 +25,46 @@ class ReproduceIssueTest { ?: error("Test resource $path not found") } + private fun checkFieldNamesMatch(baselineNode: JsonNode, currentNode: JsonNode, path: String) { + val baselineKeys = baselineNode.fieldNames().asSequence().toSet() + val currentKeys = currentNode.fieldNames().asSequence().toSet() + + val missingKeys = baselineKeys - currentKeys + assertTrue(missingKeys.isEmpty(), "Missing keys at $path: $missingKeys. Current keys: $currentKeys") + } + @Test - fun testObjectMapperWithoutKotlinModule() { + fun testMai2UserPlaylogAllFieldNamesMatchBaseline() { + val mai2Playlog = Mai2UserPlaylog().apply { + musicId = 11479 + level = 2 + achievement = 1000000 + deluxscore = 2000 + isClear = true + isTap = true + isHold = true + isSlide = true + isTouch = true + isBreak = true + isCriticalDisp = true + isFastLateDisp = true + isAchieveNewRecord = true + isDeluxscoreNewRecord = true + isPlayTutorial = true + isEventMode = false + isFreedomMode = false + isNewFree = true + } + + val currentTree = JACKSON.readTree(JACKSON.writeValueAsString(mai2Playlog)) + val baselineTree = JACKSON.readTree(loadResourceJson("/json/mai2_playlog_jackson.json")) + + checkFieldNamesMatch(baselineTree, currentTree, "Mai2UserPlaylog") + assertEquals(baselineTree.fieldNames().asSequence().toSet(), currentTree.fieldNames().asSequence().toSet()) + } + + @Test + fun testMai2ExportEntityFieldNamesMatchBaseline() { val mai2Playlog = Mai2UserPlaylog().apply { musicId = 11479 level = 2 @@ -65,75 +100,19 @@ class ReproduceIssueTest { userMapList = listOf(mai2Map) } - // Standard Jackson 2 ObjectMapper() without KotlinModule strips 'is' getters: - val plainObjectMapper = ObjectMapper() - val plainJson = plainObjectMapper.writeValueAsString(mai2Export) - val plainTree = plainObjectMapper.readTree(plainJson) - val plainPlaylogNode = plainTree.at("/userPlaylogList/0") + val currentTree = JACKSON.readTree(JACKSON.writeValueAsString(mai2Export)) + val baselineTree = JACKSON.readTree(loadResourceJson("/json/mai2_export_web.json")) - assertTrue(plainPlaylogNode.has("clear"), "Plain ObjectMapper has 'clear' instead of 'isClear'") - assertTrue(plainPlaylogNode.has("fullCombo"), "Plain ObjectMapper has 'fullCombo' instead of 'isFullCombo'") - assertTrue(plainPlaylogNode.has("allPerfect"), "Plain ObjectMapper has 'allPerfect' instead of 'isAllPerfect'") - assertFalse(plainPlaylogNode.has("isClear"), "Plain ObjectMapper is missing 'isClear'") + checkFieldNamesMatch(baselineTree.at("/userData"), currentTree.at("/userData"), "/userData") + checkFieldNamesMatch(baselineTree.at("/userExtend"), currentTree.at("/userExtend"), "/userExtend") + checkFieldNamesMatch(baselineTree.at("/userOption"), currentTree.at("/userOption"), "/userOption") + checkFieldNamesMatch(baselineTree.at("/userUdemae"), currentTree.at("/userUdemae"), "/userUdemae") + checkFieldNamesMatch(baselineTree.at("/userMapList/0"), currentTree.at("/userMapList/0"), "/userMapList/0") + checkFieldNamesMatch(baselineTree.at("/userPlaylogList/0"), currentTree.at("/userPlaylogList/0"), "/userPlaylogList/0") } @Test - fun testMai2ExportSerializationAgainstBaselineResource() { - val mai2Playlog = Mai2UserPlaylog().apply { - musicId = 11479 - level = 2 - achievement = 1000000 - deluxscore = 2000 - isClear = true - isTap = true - isHold = true - isSlide = true - isTouch = true - isBreak = true - isCriticalDisp = true - isFastLateDisp = true - isAchieveNewRecord = true - isDeluxscoreNewRecord = true - isPlayTutorial = true - isEventMode = false - isFreedomMode = false - isNewFree = true - } - - val mai2Map = Mai2UserMap().apply { - mapId = 1 - distance = 100 - isLock = false - isClear = true - isComplete = true - } - - val mai2Export = Maimai2DataExport().apply { - userData = Mai2UserDetail().apply { userName = "TestUser" } - userPlaylogList = listOf(mai2Playlog) - userMapList = listOf(mai2Map) - } - - val currentJson = JACKSON.writeValueAsString(mai2Export) - val baselineJson = loadResourceJson("/json/mai2_export_web.json") - - val currentTree = JACKSON.readTree(currentJson) - val baselineTree = JACKSON.readTree(baselineJson) - - val currentPlaylogNode = currentTree.at("/userPlaylogList/0") - val baselinePlaylogNode = baselineTree.at("/userPlaylogList/0") - - assertTrue(currentPlaylogNode.has("isClear"), "Current export must have 'isClear'") - assertTrue(currentPlaylogNode.has("isFullCombo"), "Current export must have 'isFullCombo'") - assertTrue(currentPlaylogNode.has("isAllPerfect"), "Current export must have 'isAllPerfect'") - - assertEquals(baselinePlaylogNode.get("isClear").asBoolean(), currentPlaylogNode.get("isClear").asBoolean()) - assertEquals(baselinePlaylogNode.get("isFullCombo").asBoolean(), currentPlaylogNode.get("isFullCombo").asBoolean()) - assertEquals(baselinePlaylogNode.get("isAllPerfect").asBoolean(), currentPlaylogNode.get("isAllPerfect").asBoolean()) - } - - @Test - fun testChu3ExportSerializationAgainstBaselineResource() { + fun testChu3ExportEntityFieldNamesMatchBaseline() { val chu3Playlog = Chu3UserPlaylog().apply { musicId = 100 level = 1 @@ -148,23 +127,40 @@ class ReproduceIssueTest { userPlaylogList = listOf(chu3Playlog) } - val currentJson = JACKSON.writeValueAsString(chu3Export) - val baselineJson = loadResourceJson("/json/chu3_export_web.json") + val currentTree = JACKSON.readTree(JACKSON.writeValueAsString(chu3Export)) + val baselineTree = JACKSON.readTree(loadResourceJson("/json/chu3_export_web.json")) - val currentTree = JACKSON.readTree(currentJson) - val baselineTree = JACKSON.readTree(baselineJson) - - val currentPlaylogNode = currentTree.at("/userPlaylogList/0") - val baselinePlaylogNode = baselineTree.at("/userPlaylogList/0") - - assertTrue(currentPlaylogNode.has("isClear"), "Current chu3 export must have 'isClear'") - assertTrue(currentPlaylogNode.has("isFullCombo"), "Current chu3 export must have 'isFullCombo'") - assertTrue(currentPlaylogNode.has("isAllJustice"), "Current chu3 export must have 'isAllJustice'") - assertTrue(currentPlaylogNode.has("isAllPerfect"), "Current chu3 export must have 'isAllPerfect'") + checkFieldNamesMatch(baselineTree.at("/userData"), currentTree.at("/userData"), "/userData") + checkFieldNamesMatch(baselineTree.at("/userGameOption"), currentTree.at("/userGameOption"), "/userGameOption") + checkFieldNamesMatch(baselineTree.at("/userPlaylogList/0"), currentTree.at("/userPlaylogList/0"), "/userPlaylogList/0") } @Test - fun testGameFacingMaimai2PlaylogSerialization() { + fun testOngekiExportEntityFieldNamesMatchBaseline() { + val ongekiPlaylog = OngekiUserPlaylog().apply { + musicId = 200 + level = 1 + techScore = 1000000 + isFullBell = true + isFullCombo = true + isAllBreak = true + } + + val ongekiExport = OngekiDataExport().apply { + userData = OngekiUserData().apply { userName = "OngekiUser" } + userPlaylogList = listOf(ongekiPlaylog) + } + + val currentTree = JACKSON.readTree(JACKSON.writeValueAsString(ongekiExport)) + val baselineTree = JACKSON.readTree(loadResourceJson("/json/ongeki_export_web.json")) + + checkFieldNamesMatch(baselineTree.at("/userData"), currentTree.at("/userData"), "/userData") + checkFieldNamesMatch(baselineTree.at("/userOption"), currentTree.at("/userOption"), "/userOption") + checkFieldNamesMatch(baselineTree.at("/userPlaylogList/0"), currentTree.at("/userPlaylogList/0"), "/userPlaylogList/0") + } + + @Test + fun testGameFacingMaimai2PlaylogFieldNamesMatchBaseline() { val mai2Playlog = Mai2UserPlaylog().apply { musicId = 11479 level = 2 @@ -186,44 +182,12 @@ class ReproduceIssueTest { isNewFree = true } - val basicJson = BASIC_MAPPER.writeValueAsString(mai2Playlog) - val basicTree = BASIC_MAPPER.readTree(basicJson) - assertTrue(basicTree.has("isClear"), "BASIC_MAPPER playlog must have 'isClear'") - assertTrue(basicTree.has("isFullCombo"), "BASIC_MAPPER playlog must have 'isFullCombo'") - assertTrue(basicTree.has("isAllPerfect"), "BASIC_MAPPER playlog must have 'isAllPerfect'") + val currentBasicTree = BASIC_MAPPER.readTree(BASIC_MAPPER.writeValueAsString(mai2Playlog)) + val baselineBasicTree = BASIC_MAPPER.readTree(loadResourceJson("/json/mai2_playlog_basic.json")) + checkFieldNamesMatch(baselineBasicTree, currentBasicTree, "Mai2UserPlaylog (BASIC_MAPPER)") - val stringJson = STRING_MAPPER.writeValueAsString(mai2Playlog) - val stringTree = STRING_MAPPER.readTree(stringJson) - assertTrue(stringTree.has("isClear"), "STRING_MAPPER playlog must have 'isClear'") - assertTrue(stringTree.has("isFullCombo"), "STRING_MAPPER playlog must have 'isFullCombo'") - assertTrue(stringTree.has("isAllPerfect"), "STRING_MAPPER playlog must have 'isAllPerfect'") - } - - @Test - fun testJackson3JsonMapperWithKotlinModule() { - val mai2Playlog = Mai2UserPlaylog().apply { - musicId = 11479 - level = 2 - achievement = 1000000 - deluxscore = 2000 - isClear = true - } - - val mai2Export = Maimai2DataExport().apply { - userData = Mai2UserDetail().apply { userName = "TestUser" } - userPlaylogList = listOf(mai2Playlog) - } - - val j3Mapper = JsonMapper.builder() - .addModule(KotlinModule.Builder().build()) - .build() - - val j3Json = j3Mapper.writeValueAsString(mai2Export) - val j3Tree = j3Mapper.readTree(j3Json) - val j3PlaylogNode = j3Tree.at("/userPlaylogList/0") - - assertTrue(j3PlaylogNode.has("isClear"), "Jackson 3 JsonMapper with KotlinModule must have 'isClear'") - assertTrue(j3PlaylogNode.has("isFullCombo"), "Jackson 3 JsonMapper with KotlinModule must have 'isFullCombo'") - assertTrue(j3PlaylogNode.has("isAllPerfect"), "Jackson 3 JsonMapper with KotlinModule must have 'isAllPerfect'") + val currentStringTree = STRING_MAPPER.readTree(STRING_MAPPER.writeValueAsString(mai2Playlog)) + val baselineStringTree = STRING_MAPPER.readTree(loadResourceJson("/json/mai2_playlog_string.json")) + checkFieldNamesMatch(baselineStringTree, currentStringTree, "Mai2UserPlaylog (STRING_MAPPER)") } }