Skip to content

Commit e3db559

Browse files
committed
Improve valid value providers
1 parent f6ae9bd commit e3db559

File tree

7 files changed

+98
-57
lines changed

7 files changed

+98
-57
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/util/SpringModelUtils.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ object SpringModelUtils {
8181
.filter { utContext.classLoader.tryLoadClass(it.name) != null }
8282

8383
val notEmptyClassIds get() = validationClassIds("NotEmpty")
84+
val notBlankClassIds get() = validationClassIds("NotBlank")
8485
val emailClassIds get() = validationClassIds("Email")
8586

8687

utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestConcreteExecutionContext.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import org.utbot.fuzzing.spring.GeneratedFieldValueProvider
3030
import org.utbot.fuzzing.spring.SpringBeanValueProvider
3131
import org.utbot.fuzzing.spring.preserveProperties
3232
import org.utbot.fuzzing.spring.valid.EmailValueProvider
33+
import org.utbot.fuzzing.spring.valid.NotBlankStringValueProvider
3334
import org.utbot.fuzzing.spring.valid.NotEmptyStringValueProvider
3435
import org.utbot.fuzzing.spring.valid.ValidEntityValueProvider
3536
import org.utbot.instrumentation.ConcreteExecutor
@@ -102,6 +103,7 @@ class SpringIntegrationTestConcreteExecutionContext(
102103
return springBeanValueProvider
103104
.withFallback(ValidEntityValueProvider(idGenerator, onlyAcceptWhenValidIsRequired = true))
104105
.withFallback(EmailValueProvider())
106+
.withFallback(NotBlankStringValueProvider())
105107
.withFallback(NotEmptyStringValueProvider())
106108
.withFallback(
107109
delegateContext.tryCreateValueProvider(concreteExecutor, classUnderTest, idGenerator)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.utbot.fuzzing.spring.valid
2+
3+
import org.utbot.framework.plugin.api.UtNullModel
4+
import org.utbot.framework.plugin.api.UtPrimitiveModel
5+
import org.utbot.framework.plugin.api.util.id
6+
import org.utbot.fuzzer.FuzzedType
7+
import org.utbot.fuzzer.FuzzedValue
8+
import org.utbot.fuzzer.fuzzed
9+
import org.utbot.fuzzing.providers.nullFuzzedValue
10+
import org.utbot.fuzzing.spring.FuzzedTypeProperty
11+
12+
abstract class AbstractPrimitiveValidValueProvider<TProp : FuzzedTypeProperty<T>, T, V> :
13+
AbstractValidValueProvider<TProp, T>() {
14+
15+
protected abstract val primitiveClass: Class<V>
16+
17+
protected abstract fun defaultValidPrimitiveValue(validationData: T): V
18+
protected abstract fun makeValid(originalValue: V, validationData: T): V
19+
protected abstract fun isNullValid(): Boolean
20+
21+
override fun acceptsType(type: FuzzedType): Boolean =
22+
primitiveClass.id == type.classId
23+
24+
final override fun makeValid(originalValue: FuzzedValue, validationData: T): FuzzedValue =
25+
when (val model = originalValue.model) {
26+
is UtNullModel -> if (isNullValid()) originalValue else defaultValidValue(validationData)
27+
is UtPrimitiveModel -> {
28+
if (primitiveClass.isInstance(model.value))
29+
primitiveFuzzedValue(makeValid(primitiveClass.cast(model.value), validationData))
30+
else
31+
originalValue
32+
}
33+
else -> originalValue
34+
}
35+
36+
final override fun defaultValidValue(validationData: T): FuzzedValue =
37+
primitiveFuzzedValue(defaultValidPrimitiveValue(validationData))
38+
39+
private fun primitiveFuzzedValue(value: V) = value?.let {
40+
UtPrimitiveModel(value).fuzzed {
41+
summary = "%var% = ${
42+
when (value) {
43+
is String -> "\"$value\""
44+
is Char -> "\'$value\'"
45+
else -> value.toString()
46+
}
47+
}"
48+
}
49+
} ?: nullFuzzedValue(primitiveClass.id)
50+
51+
}
Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,23 @@
11
package org.utbot.fuzzing.spring.valid
22

3-
import org.utbot.framework.plugin.api.UtNullModel
4-
import org.utbot.framework.plugin.api.UtPrimitiveModel
5-
import org.utbot.framework.plugin.api.util.stringClassId
6-
import org.utbot.fuzzer.FuzzedType
7-
import org.utbot.fuzzer.FuzzedValue
8-
import org.utbot.fuzzer.fuzzed
93
import org.utbot.fuzzing.spring.FuzzedTypeFlag
104

115
object EmailTypeFlag : FuzzedTypeFlag
126

13-
class EmailValueProvider : AbstractValidValueProvider<EmailTypeFlag, Unit>() {
14-
15-
companion object {
16-
private const val SAMPLE_EMAIL = "johnDoe@sample.com"
17-
}
7+
class EmailValueProvider : AbstractPrimitiveValidValueProvider<EmailTypeFlag, Unit, String>() {
8+
override val primitiveClass: Class<String>
9+
get() = String::class.java
1810

1911
override val validationDataTypeProperty get() = EmailTypeFlag
2012

21-
override fun acceptsType(type: FuzzedType) = type.classId == stringClassId
13+
override fun defaultValidPrimitiveValue(validationData: Unit): String = "johnDoe@sample.com"
2214

23-
override fun makeValid(originalValue: FuzzedValue, validationData: Unit): FuzzedValue =
24-
when (val model = originalValue.model) {
25-
is UtNullModel -> originalValue // `null` is a valid email according to `jakarta.validation.constraints.Email` javadoc
26-
is UtPrimitiveModel -> (model.value as? String)?.let { str ->
27-
if (str.contains("@")) originalValue
28-
else {
29-
val validEmailStr =
30-
if (str.isEmpty()) SAMPLE_EMAIL
31-
else str.take(str.length / 2) + "@" + str.drop(str.length / 2)
32-
UtPrimitiveModel(validEmailStr).fuzzed {
33-
summary = "%var% = \"$validEmailStr\""
34-
}
35-
}
36-
} ?: originalValue
37-
else -> originalValue
38-
}
15+
override fun makeValid(originalValue: String, validationData: Unit): String =
16+
when {
17+
originalValue.length < 2 -> "johnDoe@sample.com"
18+
else -> originalValue.take(originalValue.length / 2) + "@" + originalValue.drop(originalValue.length / 2)
19+
}
3920

40-
override fun defaultValidValue(validationData: Unit) = UtPrimitiveModel(SAMPLE_EMAIL).fuzzed {
41-
summary = "%var% = \"$SAMPLE_EMAIL\""
42-
}
21+
// `null` is a valid email according to `jakarta.validation.constraints.Email` javadoc
22+
override fun isNullValid(): Boolean = true
4323
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.utbot.fuzzing.spring.valid
2+
3+
import org.utbot.fuzzing.spring.FuzzedTypeFlag
4+
5+
object NotBlankTypeFlag : FuzzedTypeFlag
6+
7+
class NotBlankStringValueProvider : AbstractPrimitiveValidValueProvider<NotBlankTypeFlag, Unit, String>() {
8+
override val primitiveClass: Class<String>
9+
get() = String::class.java
10+
11+
override val validationDataTypeProperty get() = NotBlankTypeFlag
12+
13+
override fun defaultValidPrimitiveValue(validationData: Unit): String = "e"
14+
15+
override fun makeValid(originalValue: String, validationData: Unit): String =
16+
originalValue.ifBlank { "e" }
17+
18+
override fun isNullValid(): Boolean = false
19+
}
Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,19 @@
11
package org.utbot.fuzzing.spring.valid
22

3-
import org.utbot.framework.plugin.api.UtNullModel
4-
import org.utbot.framework.plugin.api.UtPrimitiveModel
5-
import org.utbot.framework.plugin.api.util.stringClassId
6-
import org.utbot.fuzzer.FuzzedType
7-
import org.utbot.fuzzer.FuzzedValue
8-
import org.utbot.fuzzer.fuzzed
93
import org.utbot.fuzzing.spring.FuzzedTypeFlag
104

115
object NotEmptyTypeFlag : FuzzedTypeFlag
126

13-
class NotEmptyStringValueProvider : AbstractValidValueProvider<NotEmptyTypeFlag, Unit>() {
14-
override val validationDataTypeProperty get() = NotEmptyTypeFlag
7+
class NotEmptyStringValueProvider : AbstractPrimitiveValidValueProvider<NotEmptyTypeFlag, Unit, String>() {
8+
override val primitiveClass: Class<String>
9+
get() = String::class.java
1510

16-
override fun acceptsType(type: FuzzedType): Boolean = type.classId == stringClassId
11+
override val validationDataTypeProperty get() = NotEmptyTypeFlag
1712

18-
override fun makeValid(originalValue: FuzzedValue, validationData: Unit): FuzzedValue =
19-
when (val model = originalValue.model) {
20-
is UtNullModel -> defaultValidValue(validationData)
21-
is UtPrimitiveModel -> {
22-
(model.value as? String)?.let {
23-
if (it.isEmpty()) defaultValidValue(validationData)
24-
else originalValue
25-
} ?: originalValue
26-
}
13+
override fun defaultValidPrimitiveValue(validationData: Unit): String = " "
2714

28-
else -> originalValue
29-
}
15+
override fun makeValid(originalValue: String, validationData: Unit): String =
16+
originalValue.ifEmpty { " " }
3017

31-
override fun defaultValidValue(validationData: Unit) = UtPrimitiveModel(" ").fuzzed {
32-
summary = "%var% = \" \""
33-
}
18+
override fun isNullValid(): Boolean = false
3419
}

utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzing/spring/valid/ValidEntity.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import org.utbot.framework.plugin.api.UtAssembleModel
99
import org.utbot.framework.plugin.api.UtDirectSetFieldModel
1010
import org.utbot.framework.plugin.api.UtExecutableCallModel
1111
import org.utbot.framework.plugin.api.UtSpringEntityManagerModel
12-
import org.utbot.framework.plugin.api.util.SpringModelUtils
1312
import org.utbot.framework.plugin.api.util.SpringModelUtils.entityClassIds
1413
import org.utbot.framework.plugin.api.util.SpringModelUtils.generatedValueClassIds
1514
import org.utbot.framework.plugin.api.util.SpringModelUtils.detachMethodIdOrNull
15+
import org.utbot.framework.plugin.api.util.SpringModelUtils.emailClassIds
1616
import org.utbot.framework.plugin.api.util.SpringModelUtils.persistMethodIdOrNull
1717
import org.utbot.framework.plugin.api.util.SpringModelUtils.idClassIds
18+
import org.utbot.framework.plugin.api.util.SpringModelUtils.notBlankClassIds
19+
import org.utbot.framework.plugin.api.util.SpringModelUtils.notEmptyClassIds
1820
import org.utbot.framework.plugin.api.util.allDeclaredFieldIds
1921
import org.utbot.framework.plugin.api.util.executableId
2022
import org.utbot.framework.plugin.api.util.id
@@ -115,8 +117,9 @@ class ValidEntityValueProvider(
115117

116118
val validationProperties = field.annotatedType.annotations.mapNotNull { annotation ->
117119
when (annotation.annotationClass.id) {
118-
in SpringModelUtils.notEmptyClassIds -> NotEmptyTypeFlag.withValue(Unit)
119-
in SpringModelUtils.emailClassIds -> EmailTypeFlag.withValue(Unit)
120+
in notEmptyClassIds -> NotEmptyTypeFlag.withValue(Unit)
121+
in notBlankClassIds -> NotBlankTypeFlag.withValue(Unit)
122+
in emailClassIds -> EmailTypeFlag.withValue(Unit)
120123
// TODO support more validators
121124
else -> null
122125
}

0 commit comments

Comments
 (0)