1
1
package org.utbot.fuzzing.providers
2
2
3
- import org.utbot.common.isAbstract
4
3
import org.utbot.framework.plugin.api.*
5
4
import org.utbot.framework.plugin.api.util.*
6
5
import org.utbot.fuzzer.*
7
6
import org.utbot.fuzzing.*
8
7
import org.utbot.fuzzing.utils.hex
8
+ import soot.Scene
9
+ import soot.SootClass
9
10
import java.lang.reflect.Field
10
11
import java.lang.reflect.Member
11
12
import java.lang.reflect.Method
12
13
import java.lang.reflect.Modifier
13
14
14
- private fun isIgnored (type : ClassId ): Boolean {
15
+ private fun isKnownTypes (type : ClassId ): Boolean {
15
16
return type == stringClassId
16
17
|| type == dateClassId
17
18
|| type == NumberValueProvider .classId
18
19
|| type.isCollectionOrMap
19
20
|| type.isPrimitiveWrapper
20
21
|| type.isEnum
22
+ }
23
+
24
+ private fun isIgnored (type : ClassId ): Boolean {
25
+ return isKnownTypes(type)
21
26
|| type.isAbstract
22
27
|| (type.isInner && ! type.isStatic)
23
28
}
@@ -33,10 +38,8 @@ class ObjectValueProvider(
33
38
type : FuzzedType
34
39
) = sequence {
35
40
val classId = type.classId
36
- val constructors = findTypesOfNonRecursiveConstructor(type, description.description.packageName)
37
- .takeIf { it.isNotEmpty() }
38
- ?.asSequence()
39
- ? : classId.allConstructors.filter {
41
+ val constructors = classId.allConstructors
42
+ .filter {
40
43
isAccessible(it.constructor , description.description.packageName)
41
44
}
42
45
constructors.forEach { constructorId ->
@@ -92,14 +95,6 @@ class ObjectValueProvider(
92
95
empty = nullRoutine(classId)
93
96
)
94
97
}
95
-
96
- private fun findTypesOfNonRecursiveConstructor (type : FuzzedType , packageName : String? ): List <ConstructorId > {
97
- return type.classId.allConstructors
98
- .filter { isAccessible(it.constructor , packageName) }
99
- .filter { c ->
100
- c.parameters.all { it.isPrimitive || it == stringClassId || it.isArray }
101
- }.toList()
102
- }
103
98
}
104
99
105
100
@Suppress(" unused" )
@@ -128,66 +123,52 @@ object NullValueProvider : ValueProvider<FuzzedType, FuzzedValue, FuzzedDescript
128
123
}
129
124
}
130
125
131
- class CreateObjectAnywayValueProvider (
126
+ /* *
127
+ * Finds and create object from implementations of abstract classes or interfaces.
128
+ */
129
+ class AbstractsObjectValueProvider (
132
130
val idGenerator : IdGenerator <Int >,
133
- val useMock : Boolean = false ,
134
131
) : ValueProvider<FuzzedType, FuzzedValue, FuzzedDescription> {
135
132
136
- override fun accept (type : FuzzedType ) = type.classId.isRefType && ! isIgnored (type.classId)
133
+ override fun accept (type : FuzzedType ) = type.classId.isRefType && ! isKnownTypes (type.classId)
137
134
138
135
override fun generate (description : FuzzedDescription , type : FuzzedType ) = sequence<Seed <FuzzedType , FuzzedValue >> {
139
- val methodCalls = description.constants.filter {
140
- it.value == CreateObjectAnywayValueProvider ::class
141
- }.mapNotNull {
142
- it.fuzzedContext as ? FuzzedContext .Call
143
- }.map {
144
- it.method
145
- }.toSet()
146
-
147
- yield (Seed .Recursive (
148
- construct = Routine .Create (emptyList()) {
149
- UtCompositeModel (idGenerator.createId(), type.classId, useMock).fuzzed {
150
- summary = " Unsafe object"
136
+ val t = Scene .v().getRefType(type.classId.canonicalName).sootClass
137
+ fun canCreateClass (sc : SootClass ): Boolean {
138
+ try {
139
+ if (! sc.isConcrete) return false
140
+ val packageName = sc.packageName
141
+ if (packageName != null ) {
142
+ if (packageName.startsWith(" jdk.internal" ) ||
143
+ packageName.startsWith(" org.utbot" ) ||
144
+ packageName.startsWith(" sun." ))
145
+ return false
151
146
}
152
- },
153
- modify = sequence {
154
- // generate all fields
155
- generateSequence(type.classId.jClass) {
156
- it.superclass
157
- }.flatMap { javaClass ->
158
- javaClass.declaredFields.toList()
159
- }.forEach { field ->
160
- yield (Routine .Call (listOf (toFuzzerType(field.type, description.typeCache))) { instance, args ->
161
- (instance.model as UtCompositeModel ).fields[field.fieldId] = args.first().model
162
- })
163
- }
164
-
165
- generateSequence(listOf (type.classId.jClass)) { classList ->
166
- classList.flatMap { listOf (it.superclass) + it.interfaces }.filterNotNull().takeIf { it.isNotEmpty() }
167
- }.flatten().filter {
168
- isAccessible(it, description.description.packageName)
169
- }.flatMap { javaClass ->
170
- javaClass.declaredMethods.filter {
171
- javaClass.isInterface || it.isAbstract
172
- }.filter {
173
- isAccessible(it, description.description.packageName)
174
- }
175
- // todo filter by methods seen in code
176
- }.forEach { method ->
177
- val executableId = method.executableId
178
- if (methodCalls.contains(executableId)) {
179
- yield (Routine .Call (listOf (toFuzzerType(method.returnType, description.typeCache))) { instance, args ->
180
- (instance.model as UtCompositeModel ).mocks[executableId] = args.map(FuzzedValue ::model)
181
- })
182
- }
183
- }
184
- },
185
- empty = Routine .Empty {
186
- UtCompositeModel (idGenerator.createId(), type.classId, useMock).fuzzed {
187
- summary = " Unsafe object"
147
+ val isAnonymousClass = sc.name.matches(""" .*\$\d+$""" .toRegex())
148
+ if (isAnonymousClass) {
149
+ return false
188
150
}
151
+ val jClass = sc.id.jClass
152
+ return isAccessible(jClass, description.description.packageName) &&
153
+ jClass.declaredConstructors.any { isAccessible(it, description.description.packageName) }
154
+ } catch (ignore: Throwable ) {
155
+ return false
189
156
}
190
- ))
157
+ }
158
+
159
+ val implementations = when {
160
+ t.isInterface -> Scene .v().fastHierarchy.getAllImplementersOfInterface(t).filter(::canCreateClass)
161
+ t.isAbstract -> Scene .v().fastHierarchy.getSubclassesOf(t).filter(::canCreateClass)
162
+ else -> emptyList()
163
+ }
164
+ implementations.shuffled(description.random).take(10 ).forEach { concrete ->
165
+ yield (Seed .Recursive (
166
+ construct = Routine .Create (listOf (toFuzzerType(concrete.id.jClass, description.typeCache))) {
167
+ it.first()
168
+ },
169
+ empty = nullRoutine(type.classId)
170
+ ))
171
+ }
191
172
}
192
173
}
193
174
0 commit comments