From 79a6ecdc0b84348b73d2c7f65570cdc044afa0f5 Mon Sep 17 00:00:00 2001 From: klaus Date: Thu, 9 Jul 2026 17:39:07 +0900 Subject: [PATCH] =?UTF-8?q?test(json):=20=EB=82=9C=EB=8F=85=ED=99=94=20?= =?UTF-8?q?=EC=95=88=EC=A0=95=EC=84=B1=20=EA=B2=80=EC=A6=9D=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../json/DtoObfuscationStabilityTest.kt | 72 +++++++++++++++++ .../json/EnumObfuscationStabilityTest.kt | 78 +++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/json/DtoObfuscationStabilityTest.kt create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/json/EnumObfuscationStabilityTest.kt diff --git a/app/src/test/java/kr/co/vividnext/sodalive/json/DtoObfuscationStabilityTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/json/DtoObfuscationStabilityTest.kt new file mode 100644 index 00000000..5647fb10 --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/json/DtoObfuscationStabilityTest.kt @@ -0,0 +1,72 @@ +package kr.co.vividnext.sodalive.json + +import com.google.gson.annotations.SerializedName +import java.io.File +import kr.co.vividnext.sodalive.audio_content.playlist.modify.UpdatePlaylistRequest +import kr.co.vividnext.sodalive.chat.original.OriginalWorkListItemResponse +import kr.co.vividnext.sodalive.chat.original.OriginalWorkListResponse +import kr.co.vividnext.sodalive.mypage.auth.AuthResponse +import kr.co.vividnext.sodalive.mypage.can.payment.payverse.PayverseVerifyRequest +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class DtoObfuscationStabilityTest { + @Test + fun `확정 DTO class는 release minify 보존 annotation을 가진다`() { + assertSourceContains("app/src/main/java/kr/co/vividnext/sodalive/mypage/auth/AuthResponse.kt", "@Keep") + assertSourceContains( + "app/src/main/java/kr/co/vividnext/sodalive/audio_content/playlist/modify/UpdatePlaylistRequest.kt", + "@Keep" + ) + assertSourceContains( + "app/src/main/java/kr/co/vividnext/sodalive/mypage/can/payment/payverse/PayverseChargeDto.kt", + "@Keep\ndata class PayverseVerifyRequest" + ) + assertSourceContains( + "app/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalWorkListResponse.kt", + "@Keep\ndata class OriginalWorkListResponse" + ) + assertSourceContains( + "app/src/main/java/kr/co/vividnext/sodalive/chat/original/OriginalWorkListResponse.kt", + "@Keep\ndata class OriginalWorkListItemResponse" + ) + } + + @Test + fun `확정 DTO field는 SerializedName으로 JSON 이름을 고정한다`() { + assertSerializedName(OriginalWorkListResponse::class.java, "totalCount", "totalCount") + assertSerializedName(OriginalWorkListResponse::class.java, "content", "content") + assertSerializedName(OriginalWorkListItemResponse::class.java, "id", "id") + assertSerializedName(OriginalWorkListItemResponse::class.java, "imageUrl", "imageUrl") + assertSerializedName(OriginalWorkListItemResponse::class.java, "title", "title") + assertSerializedName(OriginalWorkListItemResponse::class.java, "contentType", "contentType") + assertSerializedName(AuthResponse::class.java, "gender", "gender") + assertSerializedName(UpdatePlaylistRequest::class.java, "title", "title") + assertSerializedName(UpdatePlaylistRequest::class.java, "desc", "desc") + assertSerializedName(UpdatePlaylistRequest::class.java, "contentIdAndOrderList", "contentIdAndOrderList") + assertSerializedName(PayverseVerifyRequest::class.java, "transactionId", "transactionId") + assertSerializedName(PayverseVerifyRequest::class.java, "orderId", "orderId") + } + + private fun assertSourceContains(relativePath: String, expected: String) { + val source = File(projectRoot(), relativePath).readText() + assertTrue("$relativePath must contain $expected", source.contains(expected)) + } + + private fun projectRoot(): File { + val workingDirectory = File(System.getProperty("user.dir")) + return if (File(workingDirectory, "settings.gradle").exists()) { + workingDirectory + } else { + checkNotNull(workingDirectory.parentFile) { "Project root not found from $workingDirectory" } + } + } + + private fun assertSerializedName(clazz: Class<*>, fieldName: String, expectedValue: String) { + val field = clazz.getDeclaredField(fieldName) + val annotation = field.getAnnotation(SerializedName::class.java) + assertTrue("${clazz.simpleName}.$fieldName must have @SerializedName", annotation != null) + assertEquals(expectedValue, annotation?.value) + } +} diff --git a/app/src/test/java/kr/co/vividnext/sodalive/json/EnumObfuscationStabilityTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/json/EnumObfuscationStabilityTest.kt new file mode 100644 index 00000000..a22edc92 --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/json/EnumObfuscationStabilityTest.kt @@ -0,0 +1,78 @@ +package kr.co.vividnext.sodalive.json + +import com.google.gson.annotations.SerializedName +import kr.co.vividnext.sodalive.home.ContentRankingSortType +import kr.co.vividnext.sodalive.home.SeriesPublishedDaysOfWeek +import kr.co.vividnext.sodalive.v2.common.data.ContentSort +import kr.co.vividnext.sodalive.v2.main.content.data.AudioRankingType +import kr.co.vividnext.sodalive.v2.main.content.data.MainContentAllType +import kr.co.vividnext.sodalive.v2.main.content.overview.data.ContentOverviewType +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class EnumObfuscationStabilityTest { + @Test + fun `AudioRankingType은 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + AudioRankingType::class.java, + listOf("WEEKLY_POPULAR", "RISING", "REVENUE", "SALES_COUNT", "COMMENT_COUNT", "LIKE_COUNT") + ) { it.queryValue } + } + + @Test + fun `MainContentAllType은 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + MainContentAllType::class.java, + listOf("AUDIO", "SERIES", "ORIGINAL", "FREE", "POINT") + ) { it.queryValue } + } + + @Test + fun `ContentSort는 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + ContentSort::class.java, + listOf("LATEST", "POPULAR", "OWNED", "PRICE_HIGH", "PRICE_LOW") + ) { it.queryValue } + } + + @Test + fun `ContentOverviewType은 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + ContentOverviewType::class.java, + listOf("NEW_AND_HOT_AUDIO") + ) { it.queryValue } + } + + @Test + fun `SeriesPublishedDaysOfWeek는 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + SeriesPublishedDaysOfWeek::class.java, + listOf("SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT", "RANDOM") + ) { it.queryValue } + } + + @Test + fun `ContentRankingSortType은 JSON 이름과 query 값을 고정한다`() { + assertEnumWireValues( + ContentRankingSortType::class.java, + listOf("REVENUE", "SALES_COUNT", "COMMENT_COUNT", "LIKE_COUNT") + ) { it.queryValue } + } + + private fun > assertEnumWireValues( + enumClass: Class, + expectedValues: List, + queryValue: (T) -> String + ) { + val constants = enumClass.enumConstants?.toList().orEmpty() + assertEquals(expectedValues, constants.map { it.name }) + constants.zip(expectedValues).forEach { (constant, expectedValue) -> + val field = enumClass.getField(constant.name) + val annotation = field.getAnnotation(SerializedName::class.java) + assertTrue("${enumClass.simpleName}.${constant.name} must have @SerializedName", annotation != null) + assertEquals(expectedValue, annotation?.value) + assertEquals(expectedValue, queryValue(constant)) + } + } +}