@@ -11,10 +11,11 @@ import org.utbot.framework.plugin.api.*
11
11
import org.utbot.framework.plugin.api.util.*
12
12
import org.utbot.framework.util.sootMethod
13
13
import org.utbot.instrumentation.ConcreteExecutor
14
- import org.utbot.quickcheck.generator.GeneratorContext
14
+ import org.utbot.engine.greyboxfuzzer. quickcheck.generator.GeneratorContext
15
15
import java.lang.reflect.Field
16
16
import java.lang.reflect.Method
17
17
import kotlin.random.Random
18
+ import kotlin.system.exitProcess
18
19
19
20
class GreyBoxFuzzer (
20
21
private val pathsToUserClasses : String ,
@@ -29,6 +30,7 @@ class GreyBoxFuzzer(
29
30
.filter { it != - 1 }
30
31
.toSet()
31
32
private val seeds = SeedCollector (methodLines = methodLines)
33
+ private val succeededExecutions = mutableListOf<UtGreyBoxFuzzedExecution >()
32
34
private val timeRemain
33
35
get() = timeOfStart + timeBudgetInMillis - System .currentTimeMillis()
34
36
private val timeOfStart = System .currentTimeMillis()
@@ -42,37 +44,26 @@ class GreyBoxFuzzer(
42
44
val sootMethod = methodUnderTest.sootMethod
43
45
val javaMethod = sootMethod.toJavaMethod()!!
44
46
val classFieldsUsedByFunc = sootMethod.getClassFieldsUsedByFunc(javaClazz)
45
- val currentCoverageByLines = CoverageCollector .coverage
46
- .filter { it.methodSignature == methodUnderTest.signature }
47
- .map { it.lineNumber }
48
- .toSet()
49
- // TODO repeat or while
50
- while (timeRemain > 0 ) {
47
+ while (timeRemain > 0 || ! isMethodCovered()) {
51
48
explorationStage(
52
49
javaMethod,
53
- methodLines,
54
50
classFieldsUsedByFunc,
55
51
methodUnderTest,
56
- currentCoverageByLines,
57
52
generatorContext
58
53
)
59
54
logger.debug { " SEEDS AFTER EXPLORATION STAGE = ${seeds.seedsSize()} " }
60
- if (timeRemain < 0 ) break
61
- exploitationStage(
62
- methodLines,
63
- currentCoverageByLines
64
- )
55
+ if (timeRemain < 0 || isMethodCovered()) break
56
+ exploitationStage()
65
57
}
58
+ seeds.getBestSeed()
66
59
// UtModelGenerator.reset()
67
60
return sequenceOf()
68
61
}
69
62
70
63
private suspend fun explorationStage (
71
64
method : Method ,
72
- methodLinesToCover : Set <Int >,
73
65
classFieldsUsedByFunc : Set <Field >,
74
66
methodUnderTest : ExecutableId ,
75
- prevMethodCoverage : Set <Int >,
76
67
generatorContext : GeneratorContext
77
68
) {
78
69
val parametersToGenericsReplacer = method.parameters.map { it to GenericsReplacer () }
@@ -83,10 +74,9 @@ class GreyBoxFuzzer(
83
74
var iterationNumber = 0
84
75
while (System .currentTimeMillis() < endTime) {
85
76
try {
86
- logger.debug { " Iteration number $iterationNumber " }
87
- if (timeRemain < 0 ) return
77
+ if (timeRemain < 0 || isMethodCovered()) return
78
+ logger.debug { " Func: ${methodUnderTest.name} Iteration number $iterationNumber " }
88
79
iterationNumber++
89
- if (isMethodCovered(methodLinesToCover)) return
90
80
while (thisInstancesHistory.size > 1 ) {
91
81
thisInstancesHistory.removeLast()
92
82
}
@@ -137,16 +127,22 @@ class GreyBoxFuzzer(
137
127
logger.debug { " Execution started" }
138
128
val executionResult = execute(stateBefore, methodUnderTest)
139
129
logger.debug { " Execution result: $executionResult " }
140
- val seedCoverage =
141
- handleCoverage(
142
- executionResult,
143
- prevMethodCoverage,
144
- methodLinesToCover
145
- )
130
+ val seedCoverage = getCoverage(executionResult)
146
131
logger.debug { " Calculating seed score" }
147
132
val seedScore = seeds.calcSeedScore(seedCoverage)
148
133
logger.debug { " Adding seed" }
149
- seeds.addSeed(Seed (thisInstance, generatedParameters, seedCoverage, seedScore))
134
+ val seed = Seed (thisInstance, generatedParameters, seedCoverage, seedScore)
135
+ if (seeds.isSeedOpensNewCoverage(seed)) {
136
+ succeededExecutions.add(
137
+ UtGreyBoxFuzzedExecution (
138
+ stateBefore,
139
+ executionResult.result,
140
+ coverage = executionResult.coverage,
141
+ testMethodName = methodUnderTest.name
142
+ )
143
+ )
144
+ }
145
+ seeds.addSeed(seed)
150
146
logger.debug { " Execution result: ${executionResult.result} " }
151
147
logger.debug { " Seed score = $seedScore " }
152
148
} catch (e: Throwable ) {
@@ -161,38 +157,48 @@ class GreyBoxFuzzer(
161
157
}
162
158
}
163
159
164
- private suspend fun exploitationStage (
165
- methodLinesToCover : Set <Int >,
166
- prevMethodCoverage : Set <Int >
167
- ) {
160
+ private suspend fun exploitationStage () {
168
161
logger.debug { " Exploitation began" }
162
+ if (seeds.seedsSize() == 0 ) return
163
+ if (seeds.all { it.parameters.isEmpty() }) return
169
164
val startTime = System .currentTimeMillis()
170
165
val endTime = startTime + timeBudgetInMillis / percentageOfTimeBudgetToChangeMode
171
166
var iterationNumber = 0
172
167
while (System .currentTimeMillis() < endTime) {
173
- if (timeRemain < 0 ) return
174
- logger.debug { " Mutation iteration $iterationNumber " }
168
+ if (timeRemain < 0 || isMethodCovered()) return
169
+ // Infinite cycle of cant mutate seed
170
+ if (iterationNumber > 30_000 ) return
171
+ logger.debug { " Func: ${methodUnderTest.name} Mutation iteration number $iterationNumber " }
175
172
iterationNumber++
176
- if (isMethodCovered(methodLinesToCover)) return
177
- val randomSeed = seeds.getRandomWeightedSeed() ? : continue
173
+ val randomSeed = seeds.getRandomWeightedSeed()
178
174
logger.debug { " Random seed params = ${randomSeed.parameters} " }
179
- val mutatedSeed = Mutator .mutateSeed(
180
- randomSeed,
181
- GreyBoxFuzzerGenerators .sourceOfRandomness,
182
- GreyBoxFuzzerGenerators .genStatus
183
- )
175
+ val mutatedSeed =
176
+ Mutator .mutateSeed(
177
+ randomSeed,
178
+ GreyBoxFuzzerGenerators .sourceOfRandomness,
179
+ GreyBoxFuzzerGenerators .genStatus
180
+ )
181
+ if (mutatedSeed == randomSeed) {
182
+ logger.debug { " Cant mutate seed" }
183
+ continue
184
+ }
184
185
logger.debug { " Mutated params = ${mutatedSeed.parameters} " }
185
186
val stateBefore = mutatedSeed.createEnvironmentModels()
186
187
try {
187
188
val executionResult = execute(stateBefore, methodUnderTest)
188
189
logger.debug { " Execution result: $executionResult " }
189
- val seedScore =
190
- handleCoverage(
191
- executionResult,
192
- prevMethodCoverage,
193
- methodLinesToCover
194
- )
190
+ val seedScore = getCoverage(executionResult)
195
191
mutatedSeed.score = 0.0
192
+ if (seeds.isSeedOpensNewCoverage(mutatedSeed)) {
193
+ succeededExecutions.add(
194
+ UtGreyBoxFuzzedExecution (
195
+ stateBefore,
196
+ executionResult.result,
197
+ coverage = executionResult.coverage,
198
+ testMethodName = methodUnderTest.name
199
+ )
200
+ )
201
+ }
196
202
seeds.addSeed(mutatedSeed)
197
203
logger.debug { " Execution result: ${executionResult.result} " }
198
204
logger.debug { " Seed score = $seedScore " }
@@ -203,27 +209,25 @@ class GreyBoxFuzzer(
203
209
}
204
210
}
205
211
206
- private fun handleCoverage (
207
- executionResult : UtFuzzingConcreteExecutionResult ,
208
- prevMethodCoverage : Set <Int >,
209
- currentMethodLines : Set <Int >
212
+ private fun getCoverage (
213
+ executionResult : UtFuzzingConcreteExecutionResult
210
214
): Set <Int > {
211
215
val currentMethodCoverage = executionResult.coverage.coveredInstructions
212
216
.asSequence()
213
217
.filter { it.methodSignature == methodUnderTest.signature }
214
218
.map { it.lineNumber }
215
- .filter { it in currentMethodLines }
219
+ .filter { it in methodLines }
216
220
.toSet()
217
- logger.debug { " Covered lines $currentMethodCoverage from $currentMethodLines " }
221
+ logger.debug { " Covered lines $currentMethodCoverage from $methodLines " }
218
222
executionResult.coverage.coveredInstructions.forEach { CoverageCollector .coverage.add(it) }
219
223
return currentMethodCoverage
220
224
}
221
225
222
- private fun isMethodCovered (methodLinesToCover : Set < Int > ): Boolean {
226
+ private fun isMethodCovered (): Boolean {
223
227
val coveredLines =
224
228
CoverageCollector .coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.lineNumber }
225
229
.toSet()
226
- return coveredLines.containsAll(methodLinesToCover )
230
+ return coveredLines.containsAll(methodLines )
227
231
}
228
232
229
233
private suspend fun ConcreteExecutor <UtFuzzingConcreteExecutionResult , UtFuzzingExecutionInstrumentation >.executeConcretely (
0 commit comments