Skip to content

Commit f4405fa

Browse files
committed
Minor changes & documentation added
1 parent f218d6b commit f4405fa

File tree

6 files changed

+75
-53
lines changed

6 files changed

+75
-53
lines changed

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/Fuzzer.kt

-19
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import org.utbot.fuzzer.providers.EnumModelProvider
1212
import org.utbot.fuzzer.providers.ObjectModelProvider
1313
import org.utbot.fuzzer.providers.PrimitiveDefaultsModelProvider
1414
import org.utbot.fuzzer.providers.PrimitiveWrapperModelProvider
15-
import org.utbot.fuzzer.providers.PrimitivesModelProvider
1615
import org.utbot.fuzzer.providers.RegexModelProvider
1716
import org.utbot.fuzzer.providers.StringConstantModelProvider
1817
import java.util.*
@@ -145,24 +144,6 @@ fun <T> Sequence<List<FuzzedValue>>.withMutations(statistics: FuzzerStatistics<T
145144
while (yieldMutated(statistics, description, mutatorList, random)) {}
146145
}
147146

148-
/**
149-
* Creates a model provider from a list of default providers.
150-
*/
151-
fun defaultModelProviders(idGenerator: IdentityPreservingIdGenerator<Int>): ModelProvider {
152-
return ModelProvider.of(
153-
ObjectModelProvider(idGenerator),
154-
CollectionModelProvider(idGenerator),
155-
ArrayModelProvider(idGenerator),
156-
EnumModelProvider(idGenerator),
157-
ConstantsModelProvider,
158-
StringConstantModelProvider,
159-
RegexModelProvider,
160-
CharToStringModelProvider,
161-
PrimitivesModelProvider,
162-
PrimitiveWrapperModelProvider,
163-
)
164-
}
165-
166147
/**
167148
* Creates a model provider consisting of providers that do not make recursive calls inside them
168149
*/

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/ModelProvider.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ fun interface ModelProvider {
4141
}
4242
}
4343

44-
// TODO: add KDoc here
44+
/**
45+
* Applies [transform] for current provider
46+
*/
4547
fun map(transform: (ModelProvider) -> ModelProvider): ModelProvider {
4648
return if (this is Combined) {
4749
Combined(providers.map(transform))

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ArrayModelProvider.kt

+17-12
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,44 @@ import org.utbot.fuzzer.IdentityPreservingIdGenerator
1212

1313
class ArrayModelProvider(
1414
idGenerator: IdentityPreservingIdGenerator<Int>,
15-
recursion: Int = 1
16-
) : RecursiveModelProvider(idGenerator, recursion) {
17-
override fun copy(idGenerator: IdentityPreservingIdGenerator<Int>, recursionDepthLeft: Int) =
18-
ArrayModelProvider(idGenerator, recursionDepthLeft)
15+
recursionDepthLeft: Int = 1
16+
) : RecursiveModelProvider(idGenerator, recursionDepthLeft) {
17+
override fun createNewInstance(parentProvider: RecursiveModelProvider, newTotalLimit: Int): RecursiveModelProvider =
18+
ArrayModelProvider(parentProvider.idGenerator, parentProvider.recursionDepthLeft - 1)
19+
.copySettingsFrom(parentProvider)
20+
.apply {
21+
totalLimit = newTotalLimit
22+
if (parentProvider is ArrayModelProvider)
23+
branchingLimit = 1 // This improves performance but also forbids generating "jagged" arrays
24+
}
1925

2026
override fun generateModelConstructors(
2127
description: FuzzedMethodDescription,
2228
clazz: ClassId
2329
): List<ModelConstructor> {
2430
if (!clazz.isArray)
2531
return listOf()
26-
val lengths = generateArrayLengths(description).sorted()
32+
val lengths = generateArrayLengths(description)
2733
return lengths.map { length ->
2834
ModelConstructor(List(length) { clazz.elementClassId!! }) { values ->
2935
createFuzzedArrayModel(clazz, length, values.map { it.model } )
3036
}
3137
}
3238
}
3339

34-
private fun generateArrayLengths(description: FuzzedMethodDescription): Set<Int> {
35-
description.concreteValues
40+
private fun generateArrayLengths(description: FuzzedMethodDescription): List<Int> {
3641
val fuzzedLengths = fuzzValuesRecursively(
3742
types = listOf(intClassId),
3843
baseMethodDescription = description,
3944
modelProvider = ConstantsModelProvider
4045
)
4146

42-
return fuzzedLengths
47+
// Firstly we will use most "interesting" default sizes, then we will use small sizes obtained from src
48+
return listOf(3, 0) + fuzzedLengths
4349
.map { (it.single().model as UtPrimitiveModel).value as Int }
44-
.filter { it in 0..10 }
45-
.toSet()
46-
.plus(0)
47-
.plus(3)
50+
.filter { it in 1..10 && it != 3 }
51+
.toSortedSet()
52+
.toList()
4853
}
4954

5055
private fun createFuzzedArrayModel(arrayClassId: ClassId, length: Int, values: List<UtModel>?) =

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt

+10-7
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ import java.lang.reflect.Method
2424
import java.lang.reflect.Modifier.*
2525

2626
/**
27-
* Creates [UtAssembleModel] for objects which have public constructors with primitives types and String as parameters.
27+
* Creates [UtAssembleModel] for objects which have public constructors
2828
*/
2929
class ObjectModelProvider(
3030
idGenerator: IdentityPreservingIdGenerator<Int>,
31-
recursion: Int = 1,
32-
) : RecursiveModelProvider(idGenerator, recursion) {
33-
override fun copy(idGenerator: IdentityPreservingIdGenerator<Int>, recursionDepthLeft: Int) =
34-
ObjectModelProvider(idGenerator, recursionDepthLeft)
31+
recursionDepthLeft: Int = 1,
32+
) : RecursiveModelProvider(idGenerator, recursionDepthLeft) {
33+
override fun createNewInstance(parentProvider: RecursiveModelProvider, newTotalLimit: Int): RecursiveModelProvider =
34+
ObjectModelProvider(parentProvider.idGenerator, parentProvider.recursionDepthLeft - 1)
35+
.copySettingsFrom(parentProvider)
36+
.apply {
37+
totalLimit = newTotalLimit
38+
branchingLimit = 1 // When called recursively, we will use only simplest constructor
39+
}
3540

3641
override fun generateModelConstructors(
3742
description: FuzzedMethodDescription,
@@ -65,8 +70,6 @@ class ObjectModelProvider(
6570
}
6671
}
6772
}
68-
69-
//add(ModelConstructor(listOf()) { UtNullModel(clazz).fuzzed {}})
7073
}
7174
}
7275

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/RecursiveModelProvider.kt

+45-12
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,37 @@ import org.utbot.fuzzer.defaultModelProviders
1212
import org.utbot.fuzzer.exceptIsInstance
1313
import org.utbot.fuzzer.fuzz
1414

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

26+
/**
27+
* Abstraction for providers that may call other providers recursively inside them. [generate] will firstly get possible
28+
* model constructors (provided by [generateModelConstructors]) and then fuzz parameters for each of them using synthetic method
29+
*
30+
* @param recursionDepthLeft maximum recursion level, i.e. maximum number of nested calls produced by this provider
31+
*
32+
* @property modelProviderForRecursiveCalls providers that can be called by this provider.
33+
* Note that if [modelProviderForRecursiveCalls] has instances of [RecursiveModelProvider] then this provider will use
34+
* their copies created by [createNewInstance] rather than themselves (this is important because we have to change some
35+
* properties like [recursionDepthLeft], [totalLimit], etc.)
36+
*
37+
* @property fallbackProvider provider that will be used instead [modelProviderForRecursiveCalls] after reaching maximum recursion level
38+
*
39+
* @property totalLimit maximum number of parameters produced by this provider
40+
*
41+
* @property branchingLimit maximum number of [ModelConstructor]s used by [generate] (see [generateModelConstructors])
42+
*/
2043
abstract class RecursiveModelProvider(
21-
protected val idGenerator: IdentityPreservingIdGenerator<Int>,
22-
protected val recursionDepthLeft: Int
44+
val idGenerator: IdentityPreservingIdGenerator<Int>,
45+
val recursionDepthLeft: Int
2346
): ModelProvider {
2447
var modelProviderForRecursiveCalls: ModelProvider = defaultModelProviders(idGenerator, recursionDepthLeft - 1)
2548

@@ -33,12 +56,7 @@ abstract class RecursiveModelProvider(
3356
if (recursionDepthLeft > 0)
3457
modelProviderForRecursiveCalls.map {
3558
if (it is RecursiveModelProvider)
36-
it.copy(idGenerator, recursionDepthLeft - 1).apply {
37-
modelProviderForRecursiveCalls = this@RecursiveModelProvider.modelProviderForRecursiveCalls
38-
fallbackProvider = this@RecursiveModelProvider.fallbackProvider
39-
totalLimit = this@RecursiveModelProvider.totalLimit / numOfBranches
40-
branchingLimit = this@RecursiveModelProvider.branchingLimit
41-
}
59+
it.createNewInstance(this, totalLimit / numOfBranches)
4260
else
4361
it
4462
}
@@ -47,9 +65,24 @@ abstract class RecursiveModelProvider(
4765
.exceptIsInstance<RecursiveModelProvider>()
4866
.withFallback(fallbackProvider)
4967

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

52-
abstract fun generateModelConstructors(description: FuzzedMethodDescription, clazz: ClassId): List<ModelConstructor>
73+
/**
74+
* Creates [ModelProvider]s that will be used to generate values recursively. The order of elements in returned list is important:
75+
* only first [branchingLimit] constructors will be used, so you should place most effective providers first
76+
*/
77+
protected abstract fun generateModelConstructors(description: FuzzedMethodDescription, clazz: ClassId): List<ModelConstructor>
78+
79+
protected fun copySettingsFrom(otherProvider: RecursiveModelProvider): RecursiveModelProvider {
80+
modelProviderForRecursiveCalls = otherProvider.modelProviderForRecursiveCalls
81+
fallbackProvider = otherProvider.fallbackProvider
82+
totalLimit = otherProvider.totalLimit
83+
branchingLimit = otherProvider.branchingLimit
84+
return this
85+
}
5386

5487
final override fun generate(description: FuzzedMethodDescription): Sequence<FuzzedParameter> = sequence {
5588
description.parametersMap.asSequence().forEach { (classId, indices) ->
@@ -72,7 +105,7 @@ abstract class RecursiveModelProvider(
72105
if (types.isEmpty())
73106
return sequenceOf(listOf())
74107
val syntheticMethodDescription = FuzzedMethodDescription(
75-
"<synthetic method for RecursiveModelProvider>", // TODO: maybe add something here
108+
"<synthetic method for RecursiveModelProvider>", //TODO: maybe add more info here
76109
voidClassId,
77110
types,
78111
baseMethodDescription.concreteValues

utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt

-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import org.utbot.fuzzer.providers.ObjectModelProvider
2121
import org.utbot.fuzzer.providers.PrimitivesModelProvider
2222
import org.utbot.fuzzer.providers.StringConstantModelProvider
2323
import org.junit.jupiter.api.Assertions.*
24-
import org.junit.jupiter.api.Disabled
2524
import org.junit.jupiter.api.Test
2625
import org.utbot.framework.plugin.api.samples.FieldSetterClass
2726
import org.utbot.framework.plugin.api.samples.OuterClassWithEnums
@@ -413,7 +412,6 @@ class ModelProviderTest {
413412
}
414413
}
415414

416-
@Disabled
417415
@Test
418416
@Suppress("unused", "UNUSED_PARAMETER", "ConvertSecondaryConstructorToPrimary")
419417
fun `test complex object is constructed with the simplest inner object constructor`() {

0 commit comments

Comments
 (0)