1
1
package org.utbot.fuzzer.providers
2
2
3
+ import org.utbot.framework.plugin.api.ClassId
3
4
import org.utbot.framework.plugin.api.UtArrayModel
5
+ import org.utbot.framework.plugin.api.UtModel
6
+ import org.utbot.framework.plugin.api.UtPrimitiveModel
4
7
import org.utbot.framework.plugin.api.util.defaultValueModel
8
+ import org.utbot.framework.plugin.api.util.intClassId
5
9
import org.utbot.framework.plugin.api.util.isArray
6
10
import org.utbot.fuzzer.FuzzedMethodDescription
7
- import org.utbot.fuzzer.FuzzedParameter
8
- import org.utbot.fuzzer.IdGenerator
9
- import org.utbot.fuzzer.ModelProvider
10
- import org.utbot.fuzzer.ModelProvider.Companion.yieldAllValues
11
- import java.util.function.IntSupplier
11
+ import org.utbot.fuzzer.IdentityPreservingIdGenerator
12
12
13
13
class ArrayModelProvider (
14
- private val idGenerator : IdGenerator <Int >
15
- ) : ModelProvider {
16
- override fun generate (description : FuzzedMethodDescription ): Sequence <FuzzedParameter > = sequence {
17
- description.parametersMap
18
- .asSequence()
19
- .filter { (classId, _) -> classId.isArray }
20
- .forEach { (arrayClassId, indices) ->
21
- yieldAllValues(indices, listOf (0 , 10 ).map { arraySize ->
22
- UtArrayModel (
23
- id = idGenerator.createId(),
24
- arrayClassId,
25
- length = arraySize,
26
- arrayClassId.elementClassId!! .defaultValueModel(),
27
- mutableMapOf ()
28
- ).fuzzed {
29
- this .summary = " %var% = ${arrayClassId.elementClassId!! .simpleName} [$arraySize ]"
30
- }
31
- })
14
+ idGenerator : IdentityPreservingIdGenerator <Int >,
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
32
24
}
25
+
26
+ override fun generateModelConstructors (
27
+ description : FuzzedMethodDescription ,
28
+ classId : ClassId
29
+ ): List <ModelConstructor > {
30
+ if (! classId.isArray)
31
+ return listOf ()
32
+ val lengths = generateArrayLengths(description)
33
+ return lengths.map { length ->
34
+ ModelConstructor (List (length) { classId.elementClassId!! }) { values ->
35
+ createFuzzedArrayModel(classId, length, values.map { it.model } )
36
+ }
37
+ }
38
+ }
39
+
40
+ private fun generateArrayLengths (description : FuzzedMethodDescription ): List <Int > {
41
+ val fuzzedLengths = fuzzValuesRecursively(
42
+ types = listOf (intClassId),
43
+ baseMethodDescription = description,
44
+ modelProvider = ConstantsModelProvider
45
+ )
46
+
47
+ // Firstly we will use most "interesting" default sizes, then we will use small sizes obtained from src
48
+ return listOf (3 , 0 ) + fuzzedLengths
49
+ .map { (it.single().model as UtPrimitiveModel ).value as Int }
50
+ .filter { it in 1 .. 10 && it != 3 }
51
+ .toSortedSet()
52
+ .toList()
33
53
}
54
+
55
+ private fun createFuzzedArrayModel (arrayClassId : ClassId , length : Int , values : List <UtModel >? ) =
56
+ UtArrayModel (
57
+ idGenerator.createId(),
58
+ arrayClassId,
59
+ length,
60
+ arrayClassId.elementClassId!! .defaultValueModel(),
61
+ values?.withIndex()?.associate { it.index to it.value }?.toMutableMap() ? : mutableMapOf ()
62
+ ).fuzzed {
63
+ this .summary = " %var% = ${arrayClassId.elementClassId!! .simpleName} [$length ]"
64
+ }
34
65
}
0 commit comments