From 3f53828ba5cf5c4f79b5fd97f8fed7dadde8b815 Mon Sep 17 00:00:00 2001 From: Joel Rosario Date: Wed, 19 Jun 2024 08:09:29 +0200 Subject: [PATCH] Added negative tests --- .../in/specmatic/core/SpecmaticConfig.kt | 6 ++++-- .../specmatic/core/pattern/NumberPattern.kt | 19 ++++++++++++++++++- .../core/pattern/NumberPatternTest.kt | 13 +++++++++++++ version.properties | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/in/specmatic/core/SpecmaticConfig.kt b/core/src/main/kotlin/in/specmatic/core/SpecmaticConfig.kt index 8c2f0fb77..b759ebdc4 100644 --- a/core/src/main/kotlin/in/specmatic/core/SpecmaticConfig.kt +++ b/core/src/main/kotlin/in/specmatic/core/SpecmaticConfig.kt @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import `in`.specmatic.core.Configuration.Companion.globalConfigFileName +import `in`.specmatic.core.log.logger import `in`.specmatic.core.pattern.ContractException import java.io.File @@ -192,8 +193,9 @@ fun loadSpecmaticConfig(configFileName: String? = null): SpecmaticConfig { } try { return ObjectMapper(YAMLFactory()).readValue(configFile.readText(), SpecmaticConfig::class.java) - } catch(e: NoClassDefFoundError) { - throw Exception("This usually means that there's a dependency version conflict. If you are using Spring in a maven project, the most common resolution is to set the property to your pom project.", e) + } catch(e: LinkageError) { + logger.log(e, "A dependency version conflict has been detected. If you are using Spring in a maven project, a common resolution is to set the property to your pom project.") + throw e } catch (e: Throwable) { throw Exception("Your configuration file may have some missing configuration sections. Please ensure that the $configFileName file adheres to the schema described at: https://specmatic.in/documentation/specmatic_json.html", e) } diff --git a/core/src/main/kotlin/in/specmatic/core/pattern/NumberPattern.kt b/core/src/main/kotlin/in/specmatic/core/pattern/NumberPattern.kt index b46ed0222..2ae18e454 100644 --- a/core/src/main/kotlin/in/specmatic/core/pattern/NumberPattern.kt +++ b/core/src/main/kotlin/in/specmatic/core/pattern/NumberPattern.kt @@ -88,8 +88,25 @@ data class NumberPattern( override fun newBasedOn(row: Row, resolver: Resolver): Sequence = sequenceOf(this) override fun newBasedOn(resolver: Resolver): Sequence = sequenceOf(this) + fun ifNotInfiniteConstraint(value: Double, generateNegatives: () -> Sequence>): Sequence> { + if(value != Double.NEGATIVE_INFINITY && value != Double.POSITIVE_INFINITY) + return generateNegatives() + + return emptySequence() + } + override fun negativeBasedOn(row: Row, resolver: Resolver): Sequence> { - return scalarAnnotation(this, sequenceOf(NullPattern, BooleanPattern(), StringPattern())) + val dataTypeNegatives: Sequence = sequenceOf(NullPattern, BooleanPattern(), StringPattern()) + + val negativeForMinimumValue = ifNotInfiniteConstraint(minimum) { + sequenceOf(HasValue(ExactValuePattern(NumberValue(minimum - 1)), "value less than minimum of $minimum")) + } + + val negativeForMaximumValue = ifNotInfiniteConstraint(maximum) { + sequenceOf(HasValue(ExactValuePattern(NumberValue(maximum + 1)), "value less than minimum of $minimum")) + } + + return scalarAnnotation(this, dataTypeNegatives) + negativeForMinimumValue + negativeForMaximumValue } override fun parse(value: String, resolver: Resolver): Value { diff --git a/core/src/test/kotlin/in/specmatic/core/pattern/NumberPatternTest.kt b/core/src/test/kotlin/in/specmatic/core/pattern/NumberPatternTest.kt index 2e66d4991..2f30e9498 100644 --- a/core/src/test/kotlin/in/specmatic/core/pattern/NumberPatternTest.kt +++ b/core/src/test/kotlin/in/specmatic/core/pattern/NumberPatternTest.kt @@ -225,4 +225,17 @@ internal class NumberPatternTest { "boolean" ) } + + @Test + @Tag(GENERATION) + fun `negative values generated should include a value greater than minimum and maximum keyword values`() { + val result = NumberPattern(minimum = 10.0, maximum = 20.0).negativeBasedOn(Row(), Resolver()).map { it.value }.toList() + assertThat(result).containsExactlyInAnyOrder( + NullPattern, + StringPattern(), + BooleanPattern(), + ExactValuePattern(NumberValue(9.0)), + ExactValuePattern(NumberValue(21.0)) + ) + } } \ No newline at end of file diff --git a/version.properties b/version.properties index df4a49a5f..705a86bae 100644 --- a/version.properties +++ b/version.properties @@ -1 +1 @@ -version=1.3.27 +version=1.3.28