diff --git a/src/main/kotlin/com/tfandkusu/ga913yaml/Main.kt b/src/main/kotlin/com/tfandkusu/ga913yaml/Main.kt index 5dcc950..ab8d8ff 100644 --- a/src/main/kotlin/com/tfandkusu/ga913yaml/Main.kt +++ b/src/main/kotlin/com/tfandkusu/ga913yaml/Main.kt @@ -9,7 +9,8 @@ fun main(args: Array) { val command = args[0] when (command) { "validate" -> { - YamlParser.parse() + val screens = YamlParser.parse() + Validator.validate(screens) } "make" -> { val screens = YamlParser.parse() diff --git a/src/main/kotlin/com/tfandkusu/ga913yaml/Validator.kt b/src/main/kotlin/com/tfandkusu/ga913yaml/Validator.kt new file mode 100644 index 0000000..a49aefe --- /dev/null +++ b/src/main/kotlin/com/tfandkusu/ga913yaml/Validator.kt @@ -0,0 +1,75 @@ +package com.tfandkusu.ga913yaml + +import com.tfandkusu.ga913yaml.model.Screen + +object Validator { + fun validate(screens: List) { + checkEventNameLength(screens) + checkEventParameterKeyLength(screens) + checkEventCount(screens) + checkDuplicateEventName(screens) + } + + /** + * イベント名の長さが40文字を超えていないかチェックする。 + */ + private fun checkEventNameLength(screens: List) { + for (screen in screens) { + if (screen.eventName.length > 40) { + throw IllegalArgumentException("画面遷移イベント " + screen.className + " は40文字を超えています。") + } + for (action in screen.actions) { + if (screen.eventName.length + action.eventName.length > 40) { + throw IllegalArgumentException( + "画面内操作イベント " + screen.className + "." + action.className + " は40文字を超えています。", + ) + } + } + } + } + + /** + * イベントパラメータキーの長さが40文字を超えていないかチェックする。 + */ + private fun checkEventParameterKeyLength(screens: List) { + for (screen in screens) { + for (action in screen.actions) { + for (parameter in action.parameters) { + if (parameter.eventParameterKey.length > 40) { + throw IllegalArgumentException( + "画面内操作イベント " + screen.className + "." + action.className + " のパラメータキー " + + parameter.propertyName + " は40文字を超えています。", + ) + } + } + } + } + } + + /** + * イベント種類数が500を超えていないかチェックする。 + */ + private fun checkEventCount(screens: List) { + val eventCount = + screens.count { it.isConversionEvent } + screens.flatMap { it.actions }.count { it.isConversionEvent } + if (eventCount > 500) { + throw IllegalArgumentException("イベント種類数が500を超えています。") + } + } + + private fun checkDuplicateEventName(screens: List) { + val eventNames = mutableSetOf() + for (screen in screens) { + if (!eventNames.add(screen.eventName)) { + throw IllegalArgumentException("画面遷移イベント " + screen.className + " は他のイベントと重複しています。") + } + for (action in screen.actions) { + if (!eventNames.add(screen.eventName + action.eventName)) { + throw IllegalArgumentException( + "画面内操作イベント " + screen.className + "." + action.className + " は他のイベントと重複しています。", + ) + } + } + } + } +} diff --git a/src/test/kotlin/com/tfandkusu/ga913yaml/ValidatorTest.kt b/src/test/kotlin/com/tfandkusu/ga913yaml/ValidatorTest.kt new file mode 100644 index 0000000..956d8f5 --- /dev/null +++ b/src/test/kotlin/com/tfandkusu/ga913yaml/ValidatorTest.kt @@ -0,0 +1,254 @@ +package com.tfandkusu.ga913yaml + +import com.tfandkusu.ga913yaml.model.Action +import com.tfandkusu.ga913yaml.model.Parameter +import com.tfandkusu.ga913yaml.model.ParameterType +import com.tfandkusu.ga913yaml.model.Screen +import org.junit.Assert.assertEquals +import org.junit.Assert.fail +import org.junit.Test + +class ValidatorTest { + @Test + fun checkScreenEventNameLength() { + val screens = + listOf( + Screen( + description = "40文字を超えない画面遷移イベント", + className = "Screen1", + eventName = "a".repeat(40), + ), + Screen( + description = "40文字を超える画面遷移イベント", + className = "Screen2", + eventName = "b".repeat(41), + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals("画面遷移イベント Screen2 は40文字を超えています。", e.message) + } + } + + @Test + fun checkActionEventNameLength() { + val screens = + listOf( + Screen( + description = "画面1", + className = "Screen1", + eventName = "a".repeat(20), + actions = + listOf( + Action( + description = "40文字を超えない画面内操作イベント", + className = "Action1", + eventName = "b".repeat(20), + ), + Action( + description = "40文字を超える画面内操作イベント", + className = "Action2", + eventName = "c".repeat(21), + ), + ), + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals( + "画面内操作イベント Screen1.Action2 は40文字を超えています。", + e.message, + ) + } + } + + @Test + fun checkEventParameterKeyLength() { + val screens = + listOf( + Screen( + description = "画面1", + className = "Screen1", + eventName = "Scene1", + actions = + listOf( + Action( + description = "画面内操作1", + className = "Action1", + eventName = "Action1", + parameters = + listOf( + Parameter( + description = "40文字を超えないパラメータキー", + propertyName = "param1", + eventParameterKey = "a".repeat(40), + type = ParameterType.STRING, + ), + Parameter( + description = "40文字を超えるパラメータキー", + propertyName = "param2", + eventParameterKey = "b".repeat(41), + type = ParameterType.STRING, + ), + ), + ), + ), + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals( + "画面内操作イベント Screen1.Action1 のパラメータキー param2 は40文字を超えています。", + e.message, + ) + } + } + + @Test + fun checkEventCountWithoutException() { + val screens = + (0 until 250).map { + Screen( + description = "画面$it", + className = "Screen$it", + eventName = "Scene$it", + actions = + listOf( + Action( + description = "画面内操作1", + className = "Action1", + eventName = "Action1", + isConversionEvent = true, + ), + ), + isConversionEvent = true, + ) + } + Validator.validate(screens) + } + + @Test + fun checkEventCountWithException() { + val screens = + (0 until 250).map { + Screen( + description = "画面$it", + className = "Screen$it", + eventName = "Scene$it", + actions = + listOf( + Action( + description = "画面内操作1", + className = "Action1", + eventName = "Action1", + isConversionEvent = true, + ), + ), + isConversionEvent = true, + ) + } + + Screen( + description = "画面250", + className = "Screen250", + eventName = "Scene250", + isConversionEvent = true, + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals("イベント種類数が500を超えています。", e.message) + } + } + + @Test + fun checkScreenEventNameDuplicate() { + val screens = + listOf( + Screen( + description = "画面1", + className = "Screen1", + eventName = "Screen1", + ), + Screen( + description = "画面2", + className = "Screen2", + eventName = "Screen1", + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals("画面遷移イベント Screen2 は他のイベントと重複しています。", e.message) + } + } + + @Test + fun checkActionEventNameDuplicate() { + val screens = + listOf( + Screen( + description = "画面1", + className = "Screen1", + eventName = "Screen1", + actions = + listOf( + Action( + description = "画面内操作1", + className = "Action1", + eventName = "Action1", + ), + Action( + description = "画面内操作2", + className = "Action2", + eventName = "Action1", + ), + ), + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals("画面内操作イベント Screen1.Action2 は他のイベントと重複しています。", e.message) + } + } + + @Test + fun checkJoinedEventNameDuplicate() { + val screens = + listOf( + Screen( + description = "画面1", + className = "Screen1", + eventName = "Screen1", + actions = + listOf( + Action( + description = "画面内操作1", + className = "Action1", + eventName = "Action1", + ), + ), + ), + Screen( + description = "画面2", + className = "Screen2", + eventName = "Screen1Action1", + ), + ) + try { + Validator.validate(screens) + fail() + } catch (e: IllegalArgumentException) { + assertEquals("画面遷移イベント Screen2 は他のイベントと重複しています。", e.message) + } + } +}