Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce object creation using builders for fuzzers #2583

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
43 changes: 41 additions & 2 deletions utbot-fuzzing/src/main/kotlin/org/utbot/fuzzing/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ sealed interface Seed<TYPE, RESULT> {
class Recursive<TYPE, RESULT>(
val construct: Routine.Create<TYPE, RESULT>,
val modify: Sequence<Routine.Call<TYPE, RESULT>> = emptySequence(),
val empty: Routine.Empty<TYPE, RESULT>
val empty: Routine.Empty<TYPE, RESULT>,
val transformers: Sequence<Routine.Modify<TYPE, RESULT>> = emptySequence(),
Markoutte marked this conversation as resolved.
Show resolved Hide resolved
) : Seed<TYPE, RESULT>

/**
Expand Down Expand Up @@ -186,6 +187,13 @@ sealed class Routine<T, R>(val types: List<T>) : Iterable<T> by types {
}
}

class Modify<T, R>(
types: List<T>,
val callable: (instance: R, arguments: List<R>) -> R
) : Routine<T, R>(types) {
operator fun invoke(instance: R, arguments: List<R>): R = callable(instance, arguments)
}

/**
* Creates a collection of concrete sizes.
*/
Expand Down Expand Up @@ -541,7 +549,28 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
parameterIndex = -1
}
)
},
transformers = task.transformers.let { transformer ->
if (transformer === emptySequence<Node<TYPE, RESULT>>() || transformer.none()) {
emptyList()
} else {
transformer.map { f ->
fuzz(
f.types,
fuzzing,
description,
random,
configuration,
f,
state.copy {
recursionTreeDepth++
iterations = -1
parameterIndex = -1
}
)
}.toList()
}
}
)
} catch (nsv: NoSeedValueException) {
@Suppress("UNCHECKED_CAST")
Expand Down Expand Up @@ -577,7 +606,16 @@ private fun <TYPE, R> create(result: Result<TYPE, R>): R = when(result) {
else -> error("Undefined object call method ${func.builder}")
}
}
obj
transformers.let { transformers ->
var transformed = obj
transformers.forEach { transformer ->
transformed = when (val builder = transformer.builder) {
is Routine.Modify<TYPE, R> -> builder(obj, transformer.result.map { create(it) })
else -> error("Undefined object call method ${transformer.builder}")
}
}
transformed
}
}
is Result.Collection<TYPE, R> -> with(result) {
val collection: R = when (val c = construct.builder) {
Expand Down Expand Up @@ -659,6 +697,7 @@ sealed interface Result<TYPE, RESULT> {
class Recursive<TYPE, RESULT>(
val construct: Node<TYPE, RESULT>,
val modify: List<Node<TYPE, RESULT>>,
val transformers: List<Node<TYPE, RESULT>>,
) : Result<TYPE, RESULT>

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ data class Configuration(
*
* To stop recursion [Seed.Recursive.empty] is called to create new values.
*/
var recursionTreeDepth: Int = 4,
var recursionTreeDepth: Int = 5,

/**
* The limit of collection size to create.
Expand Down
9 changes: 6 additions & 3 deletions utbot-fuzzing/src/main/kotlin/org/utbot/fuzzing/Mutations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ sealed interface RecursiveMutations<TYPE, RESULT> : Mutation<Pair<Result.Recursi
): Result.Recursive<TYPE, RESULT> {
return Result.Recursive(
construct = recursive.mutate(source.construct,random, configuration),
modify = source.modify
modify = source.modify,
transformers = source.transformers,
)
}
}
Expand All @@ -309,7 +310,8 @@ sealed interface RecursiveMutations<TYPE, RESULT> : Mutation<Pair<Result.Recursi
): Result.Recursive<TYPE, RESULT> {
return Result.Recursive(
construct = source.construct,
modify = source.modify.shuffled(random).take(random.nextInt(source.modify.size + 1))
modify = source.modify.shuffled(random).take(random.nextInt(source.modify.size + 1)),
transformers = source.transformers
)
}
}
Expand All @@ -326,7 +328,8 @@ sealed interface RecursiveMutations<TYPE, RESULT> : Mutation<Pair<Result.Recursi
modify = source.modify.toMutableList().apply {
val i = random.nextInt(0, source.modify.size)
set(i, recursive.mutate(source.modify[i], random, configuration))
}
},
transformers = source.transformers
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,18 @@ fun defaultValueProviders(idGenerator: IdentityPreservingIdGenerator<Int>) = lis
FloatValueProvider,
StringValueProvider,
NumberValueProvider,
anyObjectValueProvider(idGenerator),
ArrayValueProvider(idGenerator),
EnumValueProvider(idGenerator),
ListSetValueProvider(idGenerator),
MapValueProvider(idGenerator),
IteratorValueProvider(idGenerator),
EmptyCollectionValueProvider(idGenerator),
DateValueProvider(idGenerator),
(ObjectValueProvider(idGenerator)
with ArrayValueProvider(idGenerator)
with EnumValueProvider(idGenerator)
with ListSetValueProvider(idGenerator)
with MapValueProvider(idGenerator)
with IteratorValueProvider(idGenerator)
with EmptyCollectionValueProvider(idGenerator)
with DateValueProvider(idGenerator))
.withFallback(
AbstractsObjectValueProvider(idGenerator)
with BuilderObjectValueProvider(idGenerator)
),
VoidValueProvider,
NullValueProvider,
)
Expand Down Expand Up @@ -235,6 +239,7 @@ private fun toClassId(type: Type, cache: MutableMap<Type, FuzzedType>): ClassId
}
is ParameterizedType -> (type.rawType as Class<*>).id
is Class<*> -> type.id
is TypeVariable<*> -> type.bounds.firstOrNull()?.let { toClassId(it, cache) } ?: objectClassId
else -> error("unknown type: $type")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class ModifyingWithMethodsProviderWrapper(
}
},
empty = seed.empty,
transformers = seed.transformers,
)
} else seed
}
Expand Down
Loading