From acc590bef5fca05bd774bd1b1134d30099e7f9ea Mon Sep 17 00:00:00 2001 From: Maksim Pelevin Date: Wed, 6 Jul 2022 15:17:55 +0300 Subject: [PATCH 1/3] Fuzzer should change objects which are created with empty constructor by its public setters #289 --- .../fuzzer/providers/ObjectModelProvider.kt | 116 ++++++++++++++++-- .../plugin/api/samples/FieldSetterClass.java | 28 +++++ .../framework/plugin/api/ModelProviderTest.kt | 45 ++++++- 3 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/FieldSetterClass.java diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt index 52d9f0c054..fcb2596908 100644 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt +++ b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt @@ -2,7 +2,10 @@ package org.utbot.fuzzer.providers import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.ConstructorId +import org.utbot.framework.plugin.api.FieldId +import org.utbot.framework.plugin.api.MethodId import org.utbot.framework.plugin.api.UtAssembleModel +import org.utbot.framework.plugin.api.UtDirectSetFieldModel import org.utbot.framework.plugin.api.UtExecutableCallModel import org.utbot.framework.plugin.api.UtStatementModel import org.utbot.framework.plugin.api.util.id @@ -10,6 +13,8 @@ import org.utbot.framework.plugin.api.util.isPrimitive import org.utbot.framework.plugin.api.util.isPrimitiveWrapper import org.utbot.framework.plugin.api.util.jClass import org.utbot.framework.plugin.api.util.stringClassId +import org.utbot.framework.plugin.api.util.voidClassId +import org.utbot.fuzzer.FuzzedConcreteValue import org.utbot.fuzzer.FuzzedMethodDescription import org.utbot.fuzzer.FuzzedValue import org.utbot.fuzzer.ModelProvider @@ -18,6 +23,8 @@ import org.utbot.fuzzer.fuzz import org.utbot.fuzzer.objectModelProviders import org.utbot.fuzzer.providers.ConstantsModelProvider.fuzzed import java.lang.reflect.Constructor +import java.lang.reflect.Field +import java.lang.reflect.Method import java.lang.reflect.Modifier import java.util.function.BiConsumer import java.util.function.IntSupplier @@ -33,6 +40,16 @@ class ObjectModelProvider : ModelProvider { private val recursion: Int private val limit: Int + private val nonRecursiveModelProvider: ModelProvider + get() { + val modelProviderWithoutRecursion = modelProvider.exceptIsInstance() + return if (recursion > 0) { + ObjectModelProvider(idGenerator, limit = 1, recursion - 1).with(modelProviderWithoutRecursion) + } else { + modelProviderWithoutRecursion.withFallback(NullModelProvider) + } + } + constructor(idGenerator: IntSupplier) : this(idGenerator, Int.MAX_VALUE) constructor(idGenerator: IntSupplier, limit: Int) : this(idGenerator, limit, 1) @@ -55,20 +72,16 @@ class ObjectModelProvider : ModelProvider { primitiveParameterizedConstructorsFirstAndThenByParameterCount ).take(limit) } - .associateWith { constructorId -> - val modelProviderWithoutRecursion = modelProvider.exceptIsInstance() + .associateWith { constructorId -> fuzzParameters( constructorId, - if (recursion > 0) { - ObjectModelProvider(idGenerator, limit = 1, recursion - 1).with(modelProviderWithoutRecursion) - } else { - modelProviderWithoutRecursion.withFallback(NullModelProvider) - } + nonRecursiveModelProvider ) } .flatMap { (constructorId, fuzzedParameters) -> if (constructorId.parameters.isEmpty()) { - sequenceOf(assembleModel(idGenerator.asInt, constructorId, emptyList())) + sequenceOf(assembleModel(idGenerator.asInt, constructorId, emptyList())) + + generateModelsWithFieldsInitialization(constructorId, concreteValues) } else { fuzzedParameters.map { params -> @@ -85,6 +98,40 @@ class ObjectModelProvider : ModelProvider { } } + private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, concreteValues: Collection): Sequence { + val fields = findSuitableFields(constructorId.classId) + val syntheticClassFieldsSetterMethodDescription = FuzzedMethodDescription( + "${constructorId.classId.simpleName}", + voidClassId, + fields.map { it.classId }, + concreteValues + ) + + return fuzz(syntheticClassFieldsSetterMethodDescription, nonRecursiveModelProvider) + .map { fieldValues -> + val fuzzedModel = assembleModel(idGenerator.asInt, constructorId, emptyList()) + val assembleModel = fuzzedModel.model as? UtAssembleModel ?: error("Expected UtAssembleModel but ${fuzzedModel.model::class.java} found") + val modificationChain = assembleModel.modificationsChain as? MutableList ?: error("Modification chain must be mutable") + fieldValues.asSequence().mapIndexedNotNull { index, value -> + val field = fields[index] + when { + field.setter != null -> UtExecutableCallModel( + fuzzedModel.model, + MethodId(constructorId.classId, field.setter.name, field.setter.returnType.id, listOf(field.classId)), + listOf(value.model) + ) + field.canBeSetDirectly -> UtDirectSetFieldModel( + fuzzedModel.model, + FieldId(constructorId.classId, field.name), + value.model + ) + else -> null + } + }.forEach(modificationChain::add) + fuzzedModel + } + } + companion object { private fun collectConstructors(classId: ClassId, predicate: (Constructor<*>) -> Boolean): Sequence { return classId.jClass.declaredConstructors.asSequence() @@ -112,7 +159,8 @@ class ObjectModelProvider : ModelProvider { id, constructorId.classId, "${constructorId.classId.name}${constructorId.parameters}#" + id.toString(16), - instantiationChain + instantiationChain = instantiationChain, + modificationsChain = mutableListOf() ).apply { instantiationChain += UtExecutableCallModel(null, constructorId, params.map { it.model }, this) }.fuzzed { @@ -120,6 +168,47 @@ class ObjectModelProvider : ModelProvider { } } + private fun findSuitableFields(classId: ClassId): List { + val jClass = classId.jClass + return jClass.declaredFields.map { field -> + FieldDescription( + field.name, + field.type.id, + field.isPublic && !field.isFinal && !field.isStatic, + jClass.findPublicSetterIfHasPublicGetter(field) + ) + } + } + + private fun Class<*>.findPublicSetterIfHasPublicGetter(field: Field): Method? { + val postfixName = field.name.capitalize() + val setterName = "set$postfixName" + val getterName = "get$postfixName" + val getter = try { getDeclaredMethod(getterName) } catch (_: NoSuchMethodException) { return null } + return if (getter has Modifier.PUBLIC && getter.returnType == field.type) { + declaredMethods.find { + it has Modifier.PUBLIC && + it.name == setterName && + it.parameterCount == 1 && + it.parameterTypes[0] == field.type + } + } else { + null + } + } + private val Field.isPublic + get() = has(Modifier.PUBLIC) + + private val Field.isFinal + get() = has(Modifier.FINAL) + + private val Field.isStatic + get() = has(Modifier.STATIC) + + private infix fun Field.has(modifier: Int) = (modifiers and modifier) != 0 + + private infix fun Method.has(modifier: Int) = (modifiers and modifier) != 0 + private val primitiveParameterizedConstructorsFirstAndThenByParameterCount = compareByDescending { constructorId -> constructorId.parameters.all { classId -> @@ -128,5 +217,12 @@ class ObjectModelProvider : ModelProvider { }.thenComparingInt { constructorId -> constructorId.parameters.size } + + private class FieldDescription( + val name: String, + val classId: ClassId, + val canBeSetDirectly: Boolean, + val setter: Method?, + ) } -} \ No newline at end of file +} diff --git a/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/FieldSetterClass.java b/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/FieldSetterClass.java new file mode 100644 index 0000000000..1e4d344c3f --- /dev/null +++ b/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/FieldSetterClass.java @@ -0,0 +1,28 @@ +package org.utbot.framework.plugin.api.samples; + +@SuppressWarnings("All") +public class FieldSetterClass { + + public static int pubStaticField; + public final int pubFinalField = 0; + public int pubField; + public int pubFieldWithSetter; + private int prvField; + private int prvFieldWithSetter; + + public int getPubFieldWithSetter() { + return pubFieldWithSetter; + } + + public void setPubFieldWithSetter(int pubFieldWithSetter) { + this.pubFieldWithSetter = pubFieldWithSetter; + } + + public int getPrvFieldWithSetter() { + return prvFieldWithSetter; + } + + public void setPrvFieldWithSetter(int prvFieldWithSetter) { + this.prvFieldWithSetter = prvFieldWithSetter; + } +} diff --git a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt b/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt index 106a4a3d62..f67af2bb8d 100644 --- a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt +++ b/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt @@ -23,6 +23,7 @@ import org.utbot.fuzzer.providers.PrimitivesModelProvider import org.utbot.fuzzer.providers.StringConstantModelProvider import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test +import org.utbot.framework.plugin.api.samples.FieldSetterClass import org.utbot.framework.plugin.api.util.primitiveByWrapper import org.utbot.framework.plugin.api.util.primitiveWrappers import org.utbot.framework.plugin.api.util.voidWrapperClassId @@ -431,6 +432,48 @@ class ModelProviderTest { } } + @Test + fun `test complex object is created with setters`() { + val j = FieldSetterClass::class.java + assertEquals(6, j.declaredFields.size) + assertTrue( + setOf( + "pubStaticField", + "pubFinalField", + "pubField", + "pubFieldWithSetter", + "prvField", + "prvFieldWithSetter", + ).containsAll(j.declaredFields.map { it.name }) + ) + assertEquals(4, j.declaredMethods.size) + assertTrue( + setOf( + "getPubFieldWithSetter", + "setPubFieldWithSetter", + "getPrvFieldWithSetter", + "setPrvFieldWithSetter", + ).containsAll(j.declaredMethods.map { it.name }) + ) + + withUtContext(UtContext(this::class.java.classLoader)) { + val result = collect(ObjectModelProvider { 0 }.apply { + modelProvider = PrimitiveDefaultsModelProvider + }, parameters = listOf(FieldSetterClass::class.java.id)) + assertEquals(1, result.size) + assertEquals(2, result[0]!!.size) + assertEquals(0, (result[0]!![0] as UtAssembleModel).modificationsChain.size) { "One of models must be without any modifications" } + val expectedModificationSize = 3 + val modificationsChain = (result[0]!![1] as UtAssembleModel).modificationsChain + val actualModificationSize = modificationsChain.size + assertEquals(expectedModificationSize, actualModificationSize) { "In target class there's only $expectedModificationSize fields that can be changed, but generated $actualModificationSize modifications" } + + assertEquals("pubField", (modificationsChain[0] as UtDirectSetFieldModel).fieldId.name) + assertEquals("setPubFieldWithSetter", (modificationsChain[1] as UtExecutableCallModel).executable.name) + assertEquals("setPrvFieldWithSetter", (modificationsChain[2] as UtExecutableCallModel).executable.name) + } + } + private fun collect( modelProvider: ModelProvider, name: String = "testMethod", @@ -448,4 +491,4 @@ class ModelProviderTest { private enum class OneTwoThree { ONE, TWO, THREE } -} \ No newline at end of file +} From 77b51a9380cc065526ffd971a1ea16cb1b131616 Mon Sep 17 00:00:00 2001 From: Maksim Pelevin Date: Tue, 12 Jul 2022 09:08:26 +0300 Subject: [PATCH 2/3] Fuzzing doesn't generate test for package-private parameters --- .../org/utbot/engine/UtBotSymbolicEngine.kt | 2 + .../utbot/fuzzer/FuzzedMethodDescription.kt | 10 ++++ .../fuzzer/providers/ObjectModelProvider.kt | 57 +++++++++---------- .../samples/PackagePrivateFieldAndClass.java | 16 ++++++ .../framework/plugin/api/ModelProviderTest.kt | 37 +++++++++++- 5 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/PackagePrivateFieldAndClass.java diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt index 4313ddd5fd..73ec1bbc87 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt @@ -406,6 +406,8 @@ class UtBotSymbolicEngine( val methodUnderTestDescription = FuzzedMethodDescription(executableId, collectConstantsForFuzzer(graph)).apply { compilableName = if (methodUnderTest.isMethod) executableId.name else null + className = executableId.classId.simpleName + packageName = executableId.classId.packageName val names = graph.body.method.tags.filterIsInstance().firstOrNull()?.names parameterNameMap = { index -> names?.getOrNull(index) } } diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedMethodDescription.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedMethodDescription.kt index 86e706e804..f4b290932c 100644 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedMethodDescription.kt +++ b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedMethodDescription.kt @@ -25,6 +25,16 @@ class FuzzedMethodDescription( */ var compilableName: String? = null + /** + * Class Name + */ + var className: String? = null + + /** + * Package Name + */ + var packageName: String? = null + /** * Returns parameter name by its index in the signature */ diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt index fcb2596908..da2ed48a24 100644 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt +++ b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt @@ -24,8 +24,9 @@ import org.utbot.fuzzer.objectModelProviders import org.utbot.fuzzer.providers.ConstantsModelProvider.fuzzed import java.lang.reflect.Constructor import java.lang.reflect.Field +import java.lang.reflect.Member import java.lang.reflect.Method -import java.lang.reflect.Modifier +import java.lang.reflect.Modifier.* import java.util.function.BiConsumer import java.util.function.IntSupplier @@ -67,7 +68,7 @@ class ObjectModelProvider : ModelProvider { .filterNot { it == stringClassId || it.isPrimitiveWrapper } .flatMap { classId -> collectConstructors(classId) { javaConstructor -> - isPublic(javaConstructor) + isAccessible(javaConstructor, description.packageName) }.sortedWith( primitiveParameterizedConstructorsFirstAndThenByParameterCount ).take(limit) @@ -81,7 +82,7 @@ class ObjectModelProvider : ModelProvider { .flatMap { (constructorId, fuzzedParameters) -> if (constructorId.parameters.isEmpty()) { sequenceOf(assembleModel(idGenerator.asInt, constructorId, emptyList())) + - generateModelsWithFieldsInitialization(constructorId, concreteValues) + generateModelsWithFieldsInitialization(constructorId, description, concreteValues) } else { fuzzedParameters.map { params -> @@ -98,8 +99,8 @@ class ObjectModelProvider : ModelProvider { } } - private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, concreteValues: Collection): Sequence { - val fields = findSuitableFields(constructorId.classId) + private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, description: FuzzedMethodDescription, concreteValues: Collection): Sequence { + val fields = findSuitableFields(constructorId.classId, description) val syntheticClassFieldsSetterMethodDescription = FuzzedMethodDescription( "${constructorId.classId.simpleName}", voidClassId, @@ -115,16 +116,16 @@ class ObjectModelProvider : ModelProvider { fieldValues.asSequence().mapIndexedNotNull { index, value -> val field = fields[index] when { - field.setter != null -> UtExecutableCallModel( - fuzzedModel.model, - MethodId(constructorId.classId, field.setter.name, field.setter.returnType.id, listOf(field.classId)), - listOf(value.model) - ) field.canBeSetDirectly -> UtDirectSetFieldModel( fuzzedModel.model, FieldId(constructorId.classId, field.name), value.model ) + field.setter != null -> UtExecutableCallModel( + fuzzedModel.model, + MethodId(constructorId.classId, field.setter.name, field.setter.returnType.id, listOf(field.classId)), + listOf(value.model) + ) else -> null } }.forEach(modificationChain::add) @@ -141,8 +142,16 @@ class ObjectModelProvider : ModelProvider { } } - private fun isPublic(javaConstructor: Constructor<*>): Boolean { - return javaConstructor.modifiers and Modifier.PUBLIC != 0 + private fun isAccessible(member: Member, packageName: String?): Boolean { + return isPublic(member.modifiers) || + (isPackagePrivate(member.modifiers) && member.declaringClass.`package`.name == packageName) + } + + private fun isPackagePrivate(modifiers: Int): Boolean { + val hasAnyAccessModifier = isPrivate(modifiers) + || isProtected(modifiers) + || isProtected(modifiers) + return !hasAnyAccessModifier } private fun FuzzedMethodDescription.fuzzParameters(constructorId: ConstructorId, vararg modelProviders: ModelProvider): Sequence> { @@ -168,26 +177,26 @@ class ObjectModelProvider : ModelProvider { } } - private fun findSuitableFields(classId: ClassId): List { + private fun findSuitableFields(classId: ClassId, description: FuzzedMethodDescription): List { val jClass = classId.jClass return jClass.declaredFields.map { field -> FieldDescription( field.name, field.type.id, - field.isPublic && !field.isFinal && !field.isStatic, - jClass.findPublicSetterIfHasPublicGetter(field) + isAccessible(field, description.packageName) && !isFinal(field.modifiers) && !isStatic(field.modifiers), + jClass.findPublicSetterIfHasPublicGetter(field, description) ) } } - private fun Class<*>.findPublicSetterIfHasPublicGetter(field: Field): Method? { + private fun Class<*>.findPublicSetterIfHasPublicGetter(field: Field, description: FuzzedMethodDescription): Method? { val postfixName = field.name.capitalize() val setterName = "set$postfixName" val getterName = "get$postfixName" val getter = try { getDeclaredMethod(getterName) } catch (_: NoSuchMethodException) { return null } - return if (getter has Modifier.PUBLIC && getter.returnType == field.type) { + return if (isAccessible(getter, description.packageName) && getter.returnType == field.type) { declaredMethods.find { - it has Modifier.PUBLIC && + isAccessible(it, description.packageName) && it.name == setterName && it.parameterCount == 1 && it.parameterTypes[0] == field.type @@ -196,18 +205,6 @@ class ObjectModelProvider : ModelProvider { null } } - private val Field.isPublic - get() = has(Modifier.PUBLIC) - - private val Field.isFinal - get() = has(Modifier.FINAL) - - private val Field.isStatic - get() = has(Modifier.STATIC) - - private infix fun Field.has(modifier: Int) = (modifiers and modifier) != 0 - - private infix fun Method.has(modifier: Int) = (modifiers and modifier) != 0 private val primitiveParameterizedConstructorsFirstAndThenByParameterCount = compareByDescending { constructorId -> diff --git a/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/PackagePrivateFieldAndClass.java b/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/PackagePrivateFieldAndClass.java new file mode 100644 index 0000000000..f8975924b0 --- /dev/null +++ b/utbot-fuzzers/src/test/java/org/utbot/framework/plugin/api/samples/PackagePrivateFieldAndClass.java @@ -0,0 +1,16 @@ +package org.utbot.framework.plugin.api.samples; + +@SuppressWarnings("All") +public class PackagePrivateFieldAndClass { + + volatile int pkgField = 0; + + PackagePrivateFieldAndClass() { + + } + + PackagePrivateFieldAndClass(int value) { + pkgField = value; + } + +} diff --git a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt b/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt index f67af2bb8d..4be6de845c 100644 --- a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt +++ b/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt @@ -24,6 +24,7 @@ import org.utbot.fuzzer.providers.StringConstantModelProvider import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import org.utbot.framework.plugin.api.samples.FieldSetterClass +import org.utbot.framework.plugin.api.samples.PackagePrivateFieldAndClass import org.utbot.framework.plugin.api.util.primitiveByWrapper import org.utbot.framework.plugin.api.util.primitiveWrappers import org.utbot.framework.plugin.api.util.voidWrapperClassId @@ -469,20 +470,50 @@ class ModelProviderTest { assertEquals(expectedModificationSize, actualModificationSize) { "In target class there's only $expectedModificationSize fields that can be changed, but generated $actualModificationSize modifications" } assertEquals("pubField", (modificationsChain[0] as UtDirectSetFieldModel).fieldId.name) - assertEquals("setPubFieldWithSetter", (modificationsChain[1] as UtExecutableCallModel).executable.name) + assertEquals("pubFieldWithSetter", (modificationsChain[1] as UtDirectSetFieldModel).fieldId.name) assertEquals("setPrvFieldWithSetter", (modificationsChain[2] as UtExecutableCallModel).executable.name) } } + @Test + fun `test complex object is created with setters and package private field and constructor`() { + val j = PackagePrivateFieldAndClass::class.java + assertEquals(1, j.declaredFields.size) + assertTrue( + setOf( + "pkgField", + ).containsAll(j.declaredFields.map { it.name }) + ) + + withUtContext(UtContext(this::class.java.classLoader)) { + val result = collect(ObjectModelProvider { 0 }.apply { + modelProvider = PrimitiveDefaultsModelProvider + }, parameters = listOf(PackagePrivateFieldAndClass::class.java.id)) { + packageName = PackagePrivateFieldAndClass::class.java.`package`.name + } + assertEquals(1, result.size) + assertEquals(3, result[0]!!.size) + assertEquals(0, (result[0]!![0] as UtAssembleModel).modificationsChain.size) { "One of models must be without any modifications" } + assertEquals(0, (result[0]!![2] as UtAssembleModel).modificationsChain.size) { "Modification by constructor doesn't change fields" } + val expectedModificationSize = 1 + val modificationsChain = (result[0]!![1] as UtAssembleModel).modificationsChain + val actualModificationSize = modificationsChain.size + assertEquals(expectedModificationSize, actualModificationSize) { "In target class there's only $expectedModificationSize fields that can be changed, but generated $actualModificationSize modifications" } + + assertEquals("pkgField", (modificationsChain[0] as UtDirectSetFieldModel).fieldId.name) + } + } + private fun collect( modelProvider: ModelProvider, name: String = "testMethod", returnType: ClassId = voidClassId, parameters: List, - constants: List = emptyList() + constants: List = emptyList(), + block: FuzzedMethodDescription.() -> Unit = {} ): Map> { return mutableMapOf>().apply { - modelProvider.generate(FuzzedMethodDescription(name, returnType, parameters, constants)) { i, m -> + modelProvider.generate(FuzzedMethodDescription(name, returnType, parameters, constants).apply(block)) { i, m -> computeIfAbsent(i) { mutableListOf() }.add(m.model) } } From 64ac7139729b04378fd8253bad1b93ee1043ed3c Mon Sep 17 00:00:00 2001 From: Maksim Pelevin Date: Tue, 12 Jul 2022 10:41:36 +0300 Subject: [PATCH 3/3] Limit fuzzing cases for a field accessors --- .../org/utbot/fuzzer/providers/ObjectModelProvider.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt index da2ed48a24..a383f642e3 100644 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt +++ b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt @@ -36,6 +36,10 @@ import java.util.function.IntSupplier class ObjectModelProvider : ModelProvider { var modelProvider: ModelProvider + var limitValuesCreatedByFieldAccessors: Int = 100 + set(value) { + field = maxOf(0, value) + } private val idGenerator: IntSupplier private val recursion: Int @@ -100,6 +104,7 @@ class ObjectModelProvider : ModelProvider { } private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, description: FuzzedMethodDescription, concreteValues: Collection): Sequence { + if (limitValuesCreatedByFieldAccessors == 0) return emptySequence() val fields = findSuitableFields(constructorId.classId, description) val syntheticClassFieldsSetterMethodDescription = FuzzedMethodDescription( "${constructorId.classId.simpleName}", @@ -109,6 +114,7 @@ class ObjectModelProvider : ModelProvider { ) return fuzz(syntheticClassFieldsSetterMethodDescription, nonRecursiveModelProvider) + .take(limitValuesCreatedByFieldAccessors) // limit the number of fuzzed values in this particular case .map { fieldValues -> val fuzzedModel = assembleModel(idGenerator.asInt, constructorId, emptyList()) val assembleModel = fuzzedModel.model as? UtAssembleModel ?: error("Expected UtAssembleModel but ${fuzzedModel.model::class.java} found")