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.UtPrimitiveModel
4
6
import org.utbot.framework.plugin.api.util.defaultValueModel
7
+ import org.utbot.framework.plugin.api.util.intClassId
5
8
import org.utbot.framework.plugin.api.util.isArray
9
+ import org.utbot.framework.plugin.api.util.voidClassId
6
10
import org.utbot.fuzzer.FuzzedMethodDescription
7
11
import org.utbot.fuzzer.FuzzedParameter
8
- import org.utbot.fuzzer.IdGenerator
12
+ import org.utbot.fuzzer.FuzzedValue
13
+ import org.utbot.fuzzer.IdentityPreservingIdGenerator
9
14
import org.utbot.fuzzer.ModelProvider
10
15
import org.utbot.fuzzer.ModelProvider.Companion.yieldAllValues
11
- import java.util.function.IntSupplier
16
+ import org.utbot.fuzzer.defaultModelProviders
17
+ import org.utbot.fuzzer.fuzz
12
18
13
19
class ArrayModelProvider (
14
- private val idGenerator : IdGenerator <Int >
20
+ private val idGenerator : IdentityPreservingIdGenerator <Int >
15
21
) : ModelProvider {
22
+
23
+ private val defaultArraySize: Int = 3
24
+
16
25
override fun generate (description : FuzzedMethodDescription ): Sequence <FuzzedParameter > = sequence {
17
26
description.parametersMap
18
27
.asSequence()
19
28
.filter { (classId, _) -> classId.isArray }
20
29
.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
- }
30
+ val lengths = generateArrayLengths(description)
31
+
32
+ // Fuzz small arrays with interesting elements
33
+ yieldAllValues(indices, generateArrayRecursively(arrayClassId, description, defaultArraySize))
34
+
35
+ // Fuzz arrays with interesting lengths and default-valued elements
36
+ yieldAllValues(indices, lengths.asSequence().map { length ->
37
+ UtArrayModel (
38
+ id = idGenerator.createId(),
39
+ arrayClassId,
40
+ length = length,
41
+ arrayClassId.elementClassId!! .defaultValueModel(),
42
+ mutableMapOf ()
43
+ ).fuzzed {
44
+ this .summary = " %var% = ${arrayClassId.elementClassId!! .simpleName} [$length ]"
45
+ }
31
46
})
32
47
}
33
48
}
49
+
50
+ private fun generateArrayLengths (description : FuzzedMethodDescription ): Set <Int > {
51
+ val syntheticArrayLengthMethodDescription = FuzzedMethodDescription (
52
+ " <syntheticArrayLength>" ,
53
+ voidClassId,
54
+ listOf (intClassId),
55
+ description.concreteValues
56
+ ).apply {
57
+ packageName = description.packageName
58
+ }
59
+
60
+ return fuzz(syntheticArrayLengthMethodDescription, ConstantsModelProvider )
61
+ .map { (it.single().model as UtPrimitiveModel ).value as Int }
62
+ .filter { it in 0 .. 10 }
63
+ .toSet()
64
+ .plus(0 )
65
+ }
66
+
67
+ private fun generateArrayRecursively (arrayClassId : ClassId , description : FuzzedMethodDescription , length : Int ): Sequence <FuzzedValue > {
68
+ val elementClassId = arrayClassId.elementClassId ? : error(" expected ClassId for array but got ${arrayClassId.name} " )
69
+ val syntheticArrayElementSetterMethodDescription = FuzzedMethodDescription (
70
+ " ${arrayClassId.simpleName} OfLength$length <syntheticArrayElementSetter>" ,
71
+ voidClassId,
72
+ List (length) { elementClassId },
73
+ description.concreteValues
74
+ ).apply {
75
+ packageName = description.packageName
76
+ }
77
+ return fuzz(syntheticArrayElementSetterMethodDescription, defaultModelProviders(idGenerator)).map {
78
+ FuzzedValue (
79
+ UtArrayModel (
80
+ idGenerator.createId(),
81
+ arrayClassId,
82
+ length,
83
+ elementClassId.defaultValueModel(),
84
+ it.withIndex().associate { it.index to it.value.model }.toMutableMap()
85
+ )
86
+ )
87
+ }
88
+ }
34
89
}
0 commit comments