@@ -4,7 +4,7 @@ package org.utbot.fuzzing
4
4
import kotlinx.coroutines.yield
5
5
import mu.KotlinLogging
6
6
import org.utbot.fuzzing.seeds.KnownValue
7
- import org.utbot.fuzzing.utils.Multiset
7
+ import org.utbot.fuzzing.utils.MissedSeed
8
8
import org.utbot.fuzzing.utils.chooseOne
9
9
import org.utbot.fuzzing.utils.flipCoin
10
10
import org.utbot.fuzzing.utils.transformIfNotEmpty
@@ -56,11 +56,7 @@ interface Fuzzing<TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feed
56
56
* @param statistic statistic about fuzzing generation like elapsed time or number of the runs.
57
57
* @param configuration current used configuration; it can be changes for tuning fuzzing.
58
58
*/
59
- fun update (description : DESCRIPTION , statistic : Statistic <TYPE >, configuration : Configuration ) {
60
- if (! configuration.generateEmptyListForMissedTypes && statistic.missedTypes.isNotEmpty()) {
61
- error(" No seed candidates generated for types:\n\t ${statistic.missedTypes.joinToString(" \n\t " )} " )
62
- }
63
- }
59
+ suspend fun update (description : DESCRIPTION , statistic : Statistic <TYPE , RESULT >, configuration : Configuration ) {}
64
60
}
65
61
66
62
/* *
@@ -270,8 +266,8 @@ suspend fun <T, R, D : Description<T>, F : Feedback<T, R>> Fuzzing<T, R, D, F>.f
270
266
class StatImpl (
271
267
override var totalRuns : Long = 0 ,
272
268
val startTime : Long = System .nanoTime(),
273
- override var missedTypes : Multiset < T > = Multiset (),
274
- ) : Statistic<T> {
269
+ override var missedTypes : MissedSeed < T , R > = MissedSeed (),
270
+ ) : Statistic<T, R > {
275
271
override val elapsedTime: Long
276
272
get() = System .nanoTime() - startTime
277
273
}
@@ -292,17 +288,10 @@ suspend fun <T, R, D : Description<T>, F : Feedback<T, R>> Fuzzing<T, R, D, F>.f
292
288
run breaking@ {
293
289
sequence {
294
290
while (description.parameters.isNotEmpty()) {
295
- fuzzing.update(description, userStatistic, configuration)
296
291
if (dynamicallyGenerated.isNotEmpty()) {
297
292
yield (dynamicallyGenerated.removeFirst())
298
293
} else {
299
- val fuzzOne = try {
300
- fuzzOne()
301
- } catch (nsv: NoSeedValueException ) {
302
- @Suppress(" UNCHECKED_CAST" )
303
- userStatistic.missedTypes.add(nsv.type as T )
304
- continue
305
- }
294
+ val fuzzOne = fuzzOne()
306
295
// fuzz one value, seems to be bad, when have only a few and simple values
307
296
yield (fuzzOne)
308
297
@@ -320,6 +309,9 @@ suspend fun <T, R, D : Description<T>, F : Feedback<T, R>> Fuzzing<T, R, D, F>.f
320
309
}
321
310
}.forEach execution@ { values ->
322
311
yield ()
312
+ fuzzing.update(description, userStatistic.apply {
313
+ totalRuns++
314
+ }, configuration)
323
315
check(values.parameters.size == values.result.size) { " Cannot create value for ${values.parameters} " }
324
316
val valuesCache = mutableMapOf<Result <T , R >, R > ()
325
317
val result = values.result.map { valuesCache.computeIfAbsent(it) { r -> create(r) } }
@@ -405,9 +397,8 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
405
397
): Result <TYPE , RESULT > {
406
398
return if (state.recursionTreeDepth > configuration.recursionTreeDepth) {
407
399
Result .Empty { task.construct.builder(0 ) }
408
- } else {
400
+ } else try {
409
401
val iterations = when {
410
- configuration.generateEmptyListForMissedTypes && task.modify.types.any(state.missedTypes::contains) -> 0
411
402
state.iterations >= 0 && random.flipCoin(configuration.probCreateRectangleCollectionInsteadSawLike) -> state.iterations
412
403
else -> random.nextInt(0 , configuration.collectionIterations + 1 )
413
404
}
@@ -435,6 +426,14 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
435
426
},
436
427
iterations = iterations
437
428
)
429
+ } catch (nsv: NoSeedValueException ) {
430
+ @Suppress(" UNCHECKED_CAST" )
431
+ state.missedTypes[nsv.type as TYPE ] = task
432
+ if (configuration.generateEmptyCollectionsForMissedTypes) {
433
+ Result .Empty { task.construct.builder(0 ) }
434
+ } else {
435
+ throw nsv
436
+ }
438
437
}
439
438
}
440
439
@@ -452,7 +451,7 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
452
451
): Result <TYPE , RESULT > {
453
452
return if (state.recursionTreeDepth > configuration.recursionTreeDepth) {
454
453
Result .Empty { task.empty.builder() }
455
- } else {
454
+ } else try {
456
455
Result .Recursive (
457
456
construct = fuzz(
458
457
task.construct.types,
@@ -479,6 +478,14 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
479
478
take(random.nextInt(size + 1 ).coerceAtLeast(1 ))
480
479
}
481
480
)
481
+ } catch (nsv: NoSeedValueException ) {
482
+ @Suppress(" UNCHECKED_CAST" )
483
+ state.missedTypes[nsv.type as TYPE ] = task
484
+ if (configuration.generateEmptyRecursiveForMissedTypes) {
485
+ Result .Empty { task.empty() }
486
+ } else {
487
+ throw nsv
488
+ }
482
489
}
483
490
}
484
491
@@ -617,7 +624,7 @@ private data class PassRoutine<T, R>(val description: String) : Routine<T, R>(em
617
624
private class State <TYPE , RESULT >(
618
625
val recursionTreeDepth : Int = 1 ,
619
626
val cache : MutableMap <TYPE , List <Seed <TYPE , RESULT >>>,
620
- val missedTypes : Multiset <TYPE >,
627
+ val missedTypes : MissedSeed <TYPE , RESULT >,
621
628
val iterations : Int = -1 ,
622
629
)
623
630
0 commit comments