Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Minor changes & documentation added
  • Loading branch information
volivan239 committed Aug 29, 2022
commit 36c749e02fed4007f8ad679c105a370489712971
19 changes: 0 additions & 19 deletions utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/Fuzzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.utbot.fuzzer.providers.EnumModelProvider
import org.utbot.fuzzer.providers.ObjectModelProvider
import org.utbot.fuzzer.providers.PrimitiveDefaultsModelProvider
import org.utbot.fuzzer.providers.PrimitiveWrapperModelProvider
import org.utbot.fuzzer.providers.PrimitivesModelProvider
import org.utbot.fuzzer.providers.RegexModelProvider
import org.utbot.fuzzer.providers.StringConstantModelProvider
import java.util.*
Expand Down Expand Up @@ -145,24 +144,6 @@ fun <T> Sequence<List<FuzzedValue>>.withMutations(statistics: FuzzerStatistics<T
while (yieldMutated(statistics, description, mutatorList, random)) {}
}

/**
* Creates a model provider from a list of default providers.
*/
fun defaultModelProviders(idGenerator: IdentityPreservingIdGenerator<Int>): ModelProvider {
return ModelProvider.of(
ObjectModelProvider(idGenerator),
CollectionModelProvider(idGenerator),
ArrayModelProvider(idGenerator),
EnumModelProvider(idGenerator),
ConstantsModelProvider,
StringConstantModelProvider,
RegexModelProvider,
CharToStringModelProvider,
PrimitivesModelProvider,
PrimitiveWrapperModelProvider,
)
}

/**
* Creates a model provider consisting of providers that do not make recursive calls inside them
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ fun interface ModelProvider {
}
}

// TODO: add KDoc here
/**
* Applies [transform] for current provider
*/
fun map(transform: (ModelProvider) -> ModelProvider): ModelProvider {
return if (this is Combined) {
Combined(providers.map(transform))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,44 @@ import org.utbot.fuzzer.IdentityPreservingIdGenerator

class ArrayModelProvider(
idGenerator: IdentityPreservingIdGenerator<Int>,
recursion: Int = 1
) : RecursiveModelProvider(idGenerator, recursion) {
override fun copy(idGenerator: IdentityPreservingIdGenerator<Int>, recursionDepthLeft: Int) =
ArrayModelProvider(idGenerator, recursionDepthLeft)
recursionDepthLeft: Int = 1
) : RecursiveModelProvider(idGenerator, recursionDepthLeft) {
override fun createNewInstance(parentProvider: RecursiveModelProvider, newTotalLimit: Int): RecursiveModelProvider =
ArrayModelProvider(parentProvider.idGenerator, parentProvider.recursionDepthLeft - 1)
.copySettingsFrom(parentProvider)
.apply {
totalLimit = newTotalLimit
if (parentProvider is ArrayModelProvider)
branchingLimit = 1 // This improves performance but also forbids generating "jagged" arrays
}

override fun generateModelConstructors(
description: FuzzedMethodDescription,
clazz: ClassId
classId: ClassId
): List<ModelConstructor> {
if (!clazz.isArray)
if (!classId.isArray)
return listOf()
val lengths = generateArrayLengths(description).sorted()
val lengths = generateArrayLengths(description)
return lengths.map { length ->
ModelConstructor(List(length) { clazz.elementClassId!! }) { values ->
createFuzzedArrayModel(clazz, length, values.map { it.model } )
ModelConstructor(List(length) { classId.elementClassId!! }) { values ->
createFuzzedArrayModel(classId, length, values.map { it.model } )
}
}
}

private fun generateArrayLengths(description: FuzzedMethodDescription): Set<Int> {
description.concreteValues
private fun generateArrayLengths(description: FuzzedMethodDescription): List<Int> {
val fuzzedLengths = fuzzValuesRecursively(
types = listOf(intClassId),
baseMethodDescription = description,
modelProvider = ConstantsModelProvider
)

return fuzzedLengths
// Firstly we will use most "interesting" default sizes, then we will use small sizes obtained from src
return listOf(3, 0) + fuzzedLengths
.map { (it.single().model as UtPrimitiveModel).value as Int }
.filter { it in 0..10 }
.toSet()
.plus(0)
.plus(3)
.filter { it in 1..10 && it != 3 }
.toSortedSet()
.toList()
}

private fun createFuzzedArrayModel(arrayClassId: ClassId, length: Int, values: List<UtModel>?) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,28 @@ import java.lang.reflect.Method
import java.lang.reflect.Modifier.*

/**
* Creates [UtAssembleModel] for objects which have public constructors with primitives types and String as parameters.
* Creates [UtAssembleModel] for objects which have public constructors
*/
class ObjectModelProvider(
idGenerator: IdentityPreservingIdGenerator<Int>,
recursion: Int = 1,
) : RecursiveModelProvider(idGenerator, recursion) {
override fun copy(idGenerator: IdentityPreservingIdGenerator<Int>, recursionDepthLeft: Int) =
ObjectModelProvider(idGenerator, recursionDepthLeft)
recursionDepthLeft: Int = 1,
) : RecursiveModelProvider(idGenerator, recursionDepthLeft) {
override fun createNewInstance(parentProvider: RecursiveModelProvider, newTotalLimit: Int): RecursiveModelProvider =
ObjectModelProvider(parentProvider.idGenerator, parentProvider.recursionDepthLeft - 1)
.copySettingsFrom(parentProvider)
.apply {
totalLimit = newTotalLimit
branchingLimit = 1 // When called recursively, we will use only simplest constructor
}

override fun generateModelConstructors(
description: FuzzedMethodDescription,
clazz: ClassId
classId: ClassId
): List<ModelConstructor> {
if (clazz == stringClassId || clazz.isPrimitiveWrapper)
if (classId == stringClassId || classId.isPrimitiveWrapper)
return listOf()

val constructors = collectConstructors(clazz) { javaConstructor ->
val constructors = collectConstructors(classId) { javaConstructor ->
isAccessible(javaConstructor, description.packageName)
}.sortedWith(
primitiveParameterizedConstructorsFirstAndThenByParameterCount
Expand All @@ -54,7 +59,7 @@ class ObjectModelProvider(
ModelConstructor(parameters) { assembleModel(idGenerator.createId(), constructorId, it) }
)
if (parameters.isEmpty()) {
val fields = findSuitableFields(classId, description)
val fields = findSuitableFields(this.classId, description)
if (fields.isNotEmpty()) {
add(
ModelConstructor(fields.map { it.classId }) {
Expand All @@ -65,8 +70,6 @@ class ObjectModelProvider(
}
}
}

//add(ModelConstructor(listOf()) { UtNullModel(clazz).fuzzed {}})
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,37 @@ import org.utbot.fuzzer.defaultModelProviders
import org.utbot.fuzzer.exceptIsInstance
import org.utbot.fuzzer.fuzz

/**
* Auxiliary data class that stores information describing how to construct model from parts (submodels)
*
* @param neededTypes list containing type ([ClassId]) of each submodel
* @param createModel lambda that takes subModels (they should have types listed in [neededTypes]) and generates a model using them
*/
data class ModelConstructor(
val neededTypes: List<ClassId>,
val createModel: (List<FuzzedValue>) -> FuzzedValue
val createModel: (subModels: List<FuzzedValue>) -> FuzzedValue
)

/**
* Abstraction for providers that may call other providers recursively inside them. [generate] will firstly get possible
* model constructors (provided by [generateModelConstructors]) and then fuzz parameters for each of them using synthetic method
*
* @param recursionDepthLeft maximum recursion level, i.e. maximum number of nested calls produced by this provider
*
* @property modelProviderForRecursiveCalls providers that can be called by this provider.
* Note that if [modelProviderForRecursiveCalls] has instances of [RecursiveModelProvider] then this provider will use
* their copies created by [createNewInstance] rather than themselves (this is important because we have to change some
* properties like [recursionDepthLeft], [totalLimit], etc.)
*
* @property fallbackProvider provider that will be used instead [modelProviderForRecursiveCalls] after reaching maximum recursion level
*
* @property totalLimit maximum number of parameters produced by this provider
*
* @property branchingLimit maximum number of [ModelConstructor]s used by [generate] (see [generateModelConstructors])
*/
abstract class RecursiveModelProvider(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add docs

protected val idGenerator: IdentityPreservingIdGenerator<Int>,
protected val recursionDepthLeft: Int
val idGenerator: IdentityPreservingIdGenerator<Int>,
val recursionDepthLeft: Int
): ModelProvider {
var modelProviderForRecursiveCalls: ModelProvider = defaultModelProviders(idGenerator, recursionDepthLeft - 1)

Expand All @@ -33,12 +56,7 @@ abstract class RecursiveModelProvider(
if (recursionDepthLeft > 0)
modelProviderForRecursiveCalls.map {
if (it is RecursiveModelProvider)
it.copy(idGenerator, recursionDepthLeft - 1).apply {
modelProviderForRecursiveCalls = [email protected]
fallbackProvider = [email protected]
totalLimit = [email protected] / numOfBranches
branchingLimit = [email protected]
}
it.createNewInstance(this, totalLimit / numOfBranches)
else
it
}
Expand All @@ -47,9 +65,24 @@ abstract class RecursiveModelProvider(
.exceptIsInstance<RecursiveModelProvider>()
.withFallback(fallbackProvider)

abstract fun copy(idGenerator: IdentityPreservingIdGenerator<Int>, recursionDepthLeft: Int): RecursiveModelProvider
/**
* Creates instance of the class on which it is called, assuming that it will be called recursively from [parentProvider]
*/
protected abstract fun createNewInstance(parentProvider: RecursiveModelProvider, newTotalLimit: Int): RecursiveModelProvider

abstract fun generateModelConstructors(description: FuzzedMethodDescription, clazz: ClassId): List<ModelConstructor>
/**
* Creates [ModelProvider]s that will be used to generate values recursively. The order of elements in returned list is important:
* only first [branchingLimit] constructors will be used, so you should place most effective providers first
*/
protected abstract fun generateModelConstructors(description: FuzzedMethodDescription, classId: ClassId): List<ModelConstructor>

protected fun copySettingsFrom(otherProvider: RecursiveModelProvider): RecursiveModelProvider {
modelProviderForRecursiveCalls = otherProvider.modelProviderForRecursiveCalls
fallbackProvider = otherProvider.fallbackProvider
totalLimit = otherProvider.totalLimit
branchingLimit = otherProvider.branchingLimit
return this
}

final override fun generate(description: FuzzedMethodDescription): Sequence<FuzzedParameter> = sequence {
description.parametersMap.asSequence().forEach { (classId, indices) ->
Expand All @@ -72,7 +105,7 @@ abstract class RecursiveModelProvider(
if (types.isEmpty())
return sequenceOf(listOf())
val syntheticMethodDescription = FuzzedMethodDescription(
"<synthetic method for RecursiveModelProvider>", // TODO: maybe add something here
"<synthetic method for RecursiveModelProvider>", //TODO: maybe add more info here
voidClassId,
types,
baseMethodDescription.concreteValues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import org.utbot.fuzzer.providers.ObjectModelProvider
import org.utbot.fuzzer.providers.PrimitivesModelProvider
import org.utbot.fuzzer.providers.StringConstantModelProvider
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.utbot.framework.plugin.api.samples.FieldSetterClass
import org.utbot.framework.plugin.api.samples.OuterClassWithEnums
Expand Down Expand Up @@ -413,7 +412,6 @@ class ModelProviderTest {
}
}

@Disabled
@Test
@Suppress("unused", "UNUSED_PARAMETER", "ConvertSecondaryConstructorToPrimary")
fun `test complex object is constructed with the simplest inner object constructor`() {
Expand Down