diff --git a/core/src/main/kotlin/io/specmatic/core/pattern/StringPattern.kt b/core/src/main/kotlin/io/specmatic/core/pattern/StringPattern.kt index 11ae5370b..30d76a0b5 100644 --- a/core/src/main/kotlin/io/specmatic/core/pattern/StringPattern.kt +++ b/core/src/main/kotlin/io/specmatic/core/pattern/StringPattern.kt @@ -25,8 +25,9 @@ data class StringPattern( throw IllegalArgumentException("maxLength cannot be less than minLength") } regex?.let { - regexMinLengthValidation(it) - regexMaxLengthValidation(it) + val regexWithoutCaretAndDollar = it.removePrefix("^").removeSuffix("$") + regexMinLengthValidation(regexWithoutCaretAndDollar) + regexMaxLengthValidation(regexWithoutCaretAndDollar) } } @@ -46,10 +47,11 @@ data class StringPattern( private fun regexMaxLengthValidation(it: String) { maxLength?.let { maxLen -> - val regexWithoutCaretAndDollar = it.removePrefix("^").removeSuffix("$") - runCatching { - StringValue(generateFromRegex(regexWithoutCaretAndDollar, 5, maxLen + 1)) - }.getOrNull() ?: throw IllegalArgumentException("Invalid Regex - max cannot be more than regex max size") + val generatedString = generateFromRegex(it, maxLen+1) + + if (generatedString.length > maxLen) { + throw IllegalArgumentException("Invalid Regex - max cannot be more than regex max size") + } } } @@ -185,7 +187,7 @@ data class StringPattern( override val pattern: Any = "(string)" override fun toString(): String = pattern.toString() - private fun generateFromRegex(regexWithoutCaretAndDollar: String, minLength: Int, maxLength: Int?): String = + private fun generateFromRegex(regexWithoutCaretAndDollar: String, minLength: Int, maxLength: Int? = null): String = maxLength?.let { Generex(regexWithoutCaretAndDollar).random(minLength, it) } ?: Generex(regexWithoutCaretAndDollar).random(minLength) diff --git a/core/src/test/kotlin/io/specmatic/core/pattern/StringPatternTest.kt b/core/src/test/kotlin/io/specmatic/core/pattern/StringPatternTest.kt index ccaadb1d8..73d4ef33a 100644 --- a/core/src/test/kotlin/io/specmatic/core/pattern/StringPatternTest.kt +++ b/core/src/test/kotlin/io/specmatic/core/pattern/StringPatternTest.kt @@ -87,7 +87,7 @@ internal class StringPatternTest { fun regexMinLengthAndMaxLengthAndExpectedLength(): Stream { return Stream.of( Arguments.of("^[a-z]*\$", null, null, 5), - Arguments.of("^[a-z0-9]{6,}\$", 3, 10, 6), + Arguments.of("^[a-z0-9]{6,10}\$", 3, 10, 6), Arguments.of(null, 1, 10, 1), ) } @@ -205,16 +205,54 @@ internal class StringPatternTest { val result = StringPattern( minLength = minLength, maxLength = maxLength, - regex = "^[^0-9]*$" + regex = "^[^0-9]{15}$" ).negativeBasedOn(Row(), Resolver()).map { it.value }.toList() assertThat( result.filterIsInstance().filter { - it.regex == "^[^0-9]*\$_" + it.regex == "^[^0-9]{15}\$_" } ).hasSize(1) } + @Test + @Tag(GENERATION) + fun `regex sould throw validation issue for patterns less than min size as per api contract`() { + val minLength = 2 + val maxLength = 15 + + val result = runCatching { + StringPattern( + minLength = minLength, + maxLength = maxLength, + regex = "^.{0,4}$" + ).negativeBasedOn(Row(), Resolver()).map { it.value }.toList() + } + + result.onFailure { exception -> + assertThat(exception.message).isEqualTo("Invalid Regex - min cannot be less than regex least size") + } + } + + @Test + @Tag(GENERATION) + fun `regex sould throw validation issue for patterns more than max size as per api contract`() { + val minLength = 2 + val maxLength = 15 + + val result = runCatching { + StringPattern( + minLength = minLength, + maxLength = maxLength, + regex = "^.{2,14}$" + ).negativeBasedOn(Row(), Resolver()).map { it.value }.toList() + } + + result.onFailure { exception -> + assertThat(exception.message).isEqualTo("Invalid Regex - max cannot be more than regex max size") + } + } + @Test @Tag(GENERATION) fun `should exclude data type based negatives when withDataTypeNegatives config is false`() { @@ -224,7 +262,7 @@ internal class StringPatternTest { val result = StringPattern( minLength = minLength, maxLength = maxLength, - regex = "^[^0-9]*$" + regex = "^[^0-9]{15}$" ).negativeBasedOn( Row(), Resolver(), @@ -239,7 +277,7 @@ internal class StringPatternTest { ).hasSize(0) assertThat( - result.filterIsInstance().filter { it.regex == "^[^0-9]*\$_" } + result.filterIsInstance().filter { it.regex == "^[^0-9]{15}\$_" } ).hasSize(1) assertThat(