Skip to content

Commit 321865f

Browse files
New seed selection strategy and time budget for generation
1 parent cd11d9c commit 321865f

File tree

101 files changed

+790
-722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+790
-722
lines changed

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,12 @@ class UtBotSymbolicEngine(
537537
}
538538

539539
try {
540-
GreyBoxFuzzer(concreteExecutor.pathsToUserClasses, concreteExecutor.pathsToDependencyClasses, methodUnderTest).fuzz()
540+
GreyBoxFuzzer(
541+
concreteExecutor.pathsToUserClasses,
542+
concreteExecutor.pathsToDependencyClasses,
543+
methodUnderTest,
544+
120_000L
545+
).fuzz()
541546
} catch (e: CancellationException) {
542547
logger.debug { "Cancelled by timeout" }
543548
} catch (e: Throwable) {

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/GreyBoxFuzzer.kt

Lines changed: 108 additions & 137 deletions
Large diffs are not rendered by default.

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/DataGenerator.kt

Lines changed: 40 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,70 @@ import org.utbot.external.api.classIdForType
1010
import org.utbot.framework.plugin.api.ClassId
1111
import org.utbot.framework.plugin.api.UtModel
1212
import org.utbot.framework.plugin.api.UtNullModel
13+
import org.utbot.framework.plugin.api.util.id
1314
import org.utbot.framework.plugin.api.util.jClass
15+
import org.utbot.framework.plugin.api.util.objectClassId
16+
import org.utbot.quickcheck.generator.GenerationState
17+
import org.utbot.quickcheck.generator.GeneratorContext
1418
import java.lang.reflect.Parameter
1519

1620
object DataGenerator {
1721

1822
private val generatorRepository = GreyBoxFuzzerGenerators.generatorRepository
1923

20-
fun generate(
21-
clazz: Class<*>,
22-
random: SourceOfRandomness,
23-
status: GenerationStatus
24-
): UtModel? = generatorRepository.getOrProduceGenerator(clazz)?.generateImpl(random, status)
25-
26-
fun generate(
24+
fun generateUtModel(
2725
parameterTypeContext: ParameterTypeContext,
26+
depth: Int = 0,
27+
generatorContext: GeneratorContext,
2828
random: SourceOfRandomness,
2929
status: GenerationStatus
30-
): UtModel? = generatorRepository.getOrProduceGenerator(parameterTypeContext, 0)?.generateImpl(random, status)
31-
32-
fun generate(
33-
parameterTypeContext: ParameterTypeContext,
34-
random: SourceOfRandomness,
35-
status: GenerationStatus,
36-
depth: Int
37-
): UtModel? = generatorRepository.getOrProduceGenerator(parameterTypeContext, depth)?.generateImpl(random, status)
30+
): UtModel {
31+
logger.debug { "Trying to generate UtModel of type 3 times" }
32+
val classId = parameterTypeContext.rawClass.id
33+
var generatedInstance: UtModel? = null
34+
repeat(3) {
35+
generatedInstance =
36+
try {
37+
val generator =
38+
generatorRepository.getOrProduceGenerator(parameterTypeContext, generatorContext, depth)
39+
?: return@repeat
40+
generator.generatorContext.startCheckpoint()
41+
generator.generateImpl(random, status)
42+
} catch (_: Throwable) {
43+
null
44+
}
45+
generatedInstance?.let { if (it !is UtNullModel) return it }
46+
}
47+
return UtNullModel(classId)
48+
}
3849

3950
fun generate(
4051
parameter: Parameter,
4152
parameterIndex: Int,
53+
generatorContext: GeneratorContext,
4254
random: SourceOfRandomness,
4355
status: GenerationStatus
4456
): FParameter {
4557
val generator =
46-
generatorRepository.getOrProduceGenerator(parameter, parameterIndex)
58+
generatorRepository.getOrProduceGenerator(parameter, parameterIndex, generatorContext)
4759
return generate(generator, parameter, random, status)
4860
}
4961

5062
fun generateThis(
5163
classId: ClassId,
64+
generatorContext: GeneratorContext,
5265
random: SourceOfRandomness,
5366
status: GenerationStatus
5467
): NormalMethodThisInstance {
5568
val generator =
56-
generatorRepository.getOrProduceGenerator(classId.jClass)
57-
return generateThis(generator, classId, random, status)
69+
generatorRepository.getOrProduceGenerator(classId.jClass, generatorContext)
70+
return generateThis(generator, classId, generatorContext, random, status)
5871
}
5972

6073
private fun generateThis(
6174
generator: Generator?,
6275
classId: ClassId,
76+
generatorContext: GeneratorContext,
6377
random: SourceOfRandomness,
6478
status: GenerationStatus,
6579
numberOfTries: Int = 3
@@ -70,10 +84,13 @@ object DataGenerator {
7084
throw FuzzerIllegalStateException("Can't find generator for ${classId.name}")
7185
}
7286
var generatedValue: UtModel
73-
repeat(numberOfTries) {
74-
logger.debug { "Try $it" }
87+
repeat(numberOfTries) { iteration ->
88+
logger.debug { "Try $iteration" }
7589
try {
90+
generator.generationState = GenerationState.REGENERATE
91+
generator.generatorContext.startCheckpoint()
7692
generatedValue = generator.generateImpl(random, status)
93+
if (generatedValue is UtNullModel && iteration != numberOfTries - 1) return@repeat
7794
return NormalMethodThisInstance(
7895
generatedValue,
7996
generator,
@@ -104,7 +121,10 @@ object DataGenerator {
104121
repeat(numberOfTries) {
105122
logger.debug { "Try $it" }
106123
try {
124+
generator.generationState = GenerationState.REGENERATE
125+
generator.generatorContext.startCheckpoint()
107126
generatedValue = generator.generateImpl(random, status)
127+
if (generatedValue is UtNullModel) return@repeat
108128
return FParameter(
109129
parameter,
110130
null,
@@ -120,158 +140,4 @@ object DataGenerator {
120140
return FParameter(parameter, null, UtNullModel(classId), generator, classId, listOf())
121141
}
122142

123-
// //TODO Make it work with type parameters
124-
// private fun Type.getFFieldsForClass(value: Any, depth: Int, originalField: Field?): List<FField> {
125-
// println("GETTING FFIelds from $value")
126-
// createFFieldFromPrimitivesOrBoxedPrimitives(this, value, originalField)?.let { return listOf(it) }
127-
// val parameterizedType = this as? ParameterizedType
128-
// val genericsContext =
129-
// if (this is GenericArrayTypeImpl) {
130-
// (this.genericComponentType as? ParameterizedType)?.buildGenericsContext()
131-
// } else {
132-
// parameterizedType?.buildGenericsContext()
133-
// }
134-
// if (depth >= GreyBoxFuzzerGenerators.maxDepthOfGeneration) {
135-
// return emptyList()
136-
// }
137-
// val subFields = mutableListOf<FField>()
138-
// if (this.toClass()?.isArray == true) {
139-
// val arrayContentType = this.toClass()?.componentType ?: return subFields
140-
// getFFieldsFromArray(value, subFields, originalField, this, arrayContentType, depth)
141-
// return subFields
142-
// }
143-
// val classFields =
144-
// this.toClass()?.getAllDeclaredFields()?.filter { !it.hasModifiers(Modifier.FINAL) } ?: emptyList()
145-
// for (field in classFields) {
146-
// val resolvedFieldType =
147-
// if (genericsContext != null) {
148-
// //TODO make it work for subclasses
149-
// parameterizedType.let { field.resolveFieldType(genericsContext) } ?: field.type
150-
// } else {
151-
// field.type
152-
// }
153-
// assert(resolvedFieldType.toClass() != null)
154-
//// if (field.hasModifiers(Modifier.FINAL)) {
155-
//// //subFields.add(FField(field, value))
156-
//// continue
157-
//// }
158-
// if (resolvedFieldType.toClass()!!.isArray) {
159-
// val arrayOfObjects = field.getFieldValue(value)
160-
// val arrayContentType =
161-
// (resolvedFieldType as? GenericArrayTypeImpl)?.genericComponentType ?: field.type.componentType
162-
// getFFieldsFromArray(arrayOfObjects, subFields, field, resolvedFieldType, arrayContentType, depth)
163-
// //TODO!!!!
164-
// } else {
165-
// field.getFieldValue(value)?.let { fieldValue ->
166-
// try {
167-
// val generatorForField = generatorRepository.getOrProduceGenerator(field)
168-
// if (field.type.isPrimitive) {
169-
// subFields.add(FField(field, fieldValue, resolvedFieldType, generatorForField))
170-
// } else {
171-
// //println("GETTING SUBFIELDS FOR ${field.type} value = ${fieldValue} DEPTH = $depth")
172-
// //TODO resolve type
173-
// val subFFields = resolvedFieldType.getFFieldsForClass(fieldValue, depth + 1, null)
174-
// subFields.add(FField(field, fieldValue, resolvedFieldType, generatorForField, subFFields))
175-
// }
176-
// } catch (e: java.lang.IllegalStateException) {
177-
// subFields.add(FField(field, fieldValue, resolvedFieldType, null, listOf()))
178-
// }
179-
// } ?: subFields.add(FField(field, null, resolvedFieldType, null, listOf()))
180-
// }
181-
// }
182-
// return subFields
183-
// }
184-
185-
// private fun createFFieldFromPrimitivesOrBoxedPrimitives(originalType: Type, value: Any?, field: Field?): FField? {
186-
// val clazz = originalType.toClass() ?: return null
187-
// val listOfPrimitives = listOf(
188-
// Byte::class,
189-
// Short::class,
190-
// Int::class,
191-
// Long::class,
192-
// Float::class,
193-
// Double::class,
194-
// Boolean::class,
195-
// Char::class,
196-
// String::class
197-
// )
198-
// return if (clazz.kotlin in listOfPrimitives || clazz.isPrimitive) {
199-
// FField(field, value, originalType, getGenerator(originalType))
200-
// } else null
201-
// }
202-
203-
// private fun getFFieldsFromArray(
204-
// array: Any?,
205-
// subFields: MutableList<FField>,
206-
// field: Field?,
207-
// arrayType: Type,
208-
// arrayContentType: Type,
209-
// depth: Int
210-
// ) {
211-
// val typedArray =
212-
// when (array) {
213-
// is BooleanArray -> {
214-
// array.toList()
215-
// }
216-
// is ByteArray -> {
217-
// array.toList()
218-
// }
219-
// is CharArray -> {
220-
// array.toList()
221-
// }
222-
// is ShortArray -> {
223-
// array.toList()
224-
// }
225-
// is IntArray -> {
226-
// array.toList()
227-
// }
228-
// is LongArray -> {
229-
// array.toList()
230-
// }
231-
// is FloatArray -> {
232-
// array.toList()
233-
// }
234-
// is DoubleArray -> {
235-
// array.toList()
236-
// }
237-
// else -> {
238-
// if (array == null) {
239-
// subFields.add(FField(null, null, arrayContentType, null, listOf()))
240-
// return
241-
// } else {
242-
// (array as Array<*>).toList()
243-
// }
244-
// }
245-
// }
246-
// val generatorOfNeededType = field?.let { getGenerator(it, arrayType) } ?: getGenerator(arrayType)
247-
// val localSubFields = mutableListOf<FField>()
248-
// val indexOfLastNotNullElement = typedArray.indexOfLast { it != null }
249-
// val arrayContentGenerator = getGenerator(arrayContentType)
250-
// if (indexOfLastNotNullElement == -1) {
251-
// localSubFields.add(FField(field, null, arrayContentType, arrayContentGenerator))
252-
// } else {
253-
// typedArray.filterNotNull().map { el ->
254-
// val ssFFields = arrayContentType.getFFieldsForClass(el, depth + 1, null)
255-
// localSubFields.add(FField(field, el, arrayContentType, arrayContentGenerator, ssFFields))
256-
// }
257-
// }
258-
// subFields.add(FField(field, typedArray, arrayType, generatorOfNeededType, localSubFields))
259-
// }
260-
261-
// private fun getGenerator(field: Field, fieldType: Type): Generator<*>? {
262-
// return if (fieldType is ParameterizedType) {
263-
// generatorRepository.getOrProduceGenerator(field.buildParameterContext(fieldType), 0)
264-
// } else {
265-
// generatorRepository.getOrProduceGenerator(field)
266-
// }.let { gen ->
267-
// if (gen is ComponentizedGenerator && gen.getComponents().any { it is ZilchGenerator }) null
268-
// else gen
269-
// }
270-
// }
271-
// private fun getGenerator(resolvedType: Type): Generator<*>? =
272-
// generatorRepository.getOrProduceGenerator(resolvedType).let { gen ->
273-
// if (gen is ComponentizedGenerator && gen.getComponents().any { it is ZilchGenerator }) null
274-
// else gen
275-
// }
276-
277143
}

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/FParameter.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,6 @@ data class FParameter(
5050
return res
5151
}
5252

53-
fun regenerateFields() {
54-
regenerateFields(classId.jClass.getAllDeclaredFields())
55-
}
56-
57-
fun regenerateFields(fieldsToRegenerate: List<Field>) {
58-
if (utModel is UtAssembleModel) {
59-
utModel = Mutator.regenerateFields(classId.jClass, utModel as UtAssembleModel, fieldsToRegenerate)
60-
}
61-
}
62-
6353
fun copy(): FParameter = FParameter(
6454
parameter,
6555
value,

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/GeneratorConfigurator.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object GeneratorConfigurator {
2626
private val minDouble: Double = -100.0
2727
private val maxDouble: Double = 100.0
2828
private val minStringLength: Int = 1
29-
private val maxStringLength: Int = 10
29+
private val maxStringLength: Int = 5
3030
val minCollectionSize: Int = 1
3131
val maxCollectionSize: Int = 5
3232

@@ -92,10 +92,14 @@ object GeneratorConfigurator {
9292
is MapGenerator -> generator.configure(sizeAnnotationInstance)
9393
is StringGenerator -> generator.configure(
9494
if (Random.getTrue(50)) {
95-
setOf('a'.code..'z'.code)
95+
if (Random.getTrue(50)) {
96+
setOf('a'.code..'z'.code)
97+
} else {
98+
setOf('A'.code..'Z'.code)
99+
}
96100
} else {
97101
setOf(' '.code..'~'.code)
98-
}
102+
}, minStringLength..maxStringLength
99103
)
100104
else -> Unit
101105
}

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/GreyBoxFuzzerGenerators.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import java.util.*
1414
object GreyBoxFuzzerGenerators {
1515

1616
const val seed = 42L
17-
const val maxDepthOfGeneration = 4
17+
const val maxDepthOfGeneration = 7
1818
val sourceOfRandomness = SourceOfRandomness(Random(seed))
1919
val genStatus = NonTrackingGenerationStatus(sourceOfRandomness)
2020

@@ -41,7 +41,6 @@ object GreyBoxFuzzerGenerators {
4141
it.register(ShortGenerator())
4242
it.register(BooleanGenerator())
4343
it.register(IntegerGenerator())
44-
it.register(Encoded())
4544
it.register(ByteGenerator())
4645
it.register(StringGenerator())
4746
it.register(LongGenerator())

0 commit comments

Comments
 (0)