@@ -11,10 +11,11 @@ import org.utbot.framework.plugin.api.*
1111import org.utbot.framework.plugin.api.util.*
1212import org.utbot.framework.util.sootMethod
1313import org.utbot.instrumentation.ConcreteExecutor
14- import org.utbot.quickcheck.generator.GeneratorContext
14+ import org.utbot.engine.greyboxfuzzer. quickcheck.generator.GeneratorContext
1515import java.lang.reflect.Field
1616import java.lang.reflect.Method
1717import kotlin.random.Random
18+ import kotlin.system.exitProcess
1819
1920class GreyBoxFuzzer (
2021 private val pathsToUserClasses : String ,
@@ -29,6 +30,7 @@ class GreyBoxFuzzer(
2930 .filter { it != - 1 }
3031 .toSet()
3132 private val seeds = SeedCollector (methodLines = methodLines)
33+ private val succeededExecutions = mutableListOf<UtGreyBoxFuzzedExecution >()
3234 private val timeRemain
3335 get() = timeOfStart + timeBudgetInMillis - System .currentTimeMillis()
3436 private val timeOfStart = System .currentTimeMillis()
@@ -42,37 +44,26 @@ class GreyBoxFuzzer(
4244 val sootMethod = methodUnderTest.sootMethod
4345 val javaMethod = sootMethod.toJavaMethod()!!
4446 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()) {
5148 explorationStage(
5249 javaMethod,
53- methodLines,
5450 classFieldsUsedByFunc,
5551 methodUnderTest,
56- currentCoverageByLines,
5752 generatorContext
5853 )
5954 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()
6557 }
58+ seeds.getBestSeed()
6659 // UtModelGenerator.reset()
6760 return sequenceOf()
6861 }
6962
7063 private suspend fun explorationStage (
7164 method : Method ,
72- methodLinesToCover : Set <Int >,
7365 classFieldsUsedByFunc : Set <Field >,
7466 methodUnderTest : ExecutableId ,
75- prevMethodCoverage : Set <Int >,
7667 generatorContext : GeneratorContext
7768 ) {
7869 val parametersToGenericsReplacer = method.parameters.map { it to GenericsReplacer () }
@@ -83,10 +74,9 @@ class GreyBoxFuzzer(
8374 var iterationNumber = 0
8475 while (System .currentTimeMillis() < endTime) {
8576 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 " }
8879 iterationNumber++
89- if (isMethodCovered(methodLinesToCover)) return
9080 while (thisInstancesHistory.size > 1 ) {
9181 thisInstancesHistory.removeLast()
9282 }
@@ -137,16 +127,22 @@ class GreyBoxFuzzer(
137127 logger.debug { " Execution started" }
138128 val executionResult = execute(stateBefore, methodUnderTest)
139129 logger.debug { " Execution result: $executionResult " }
140- val seedCoverage =
141- handleCoverage(
142- executionResult,
143- prevMethodCoverage,
144- methodLinesToCover
145- )
130+ val seedCoverage = getCoverage(executionResult)
146131 logger.debug { " Calculating seed score" }
147132 val seedScore = seeds.calcSeedScore(seedCoverage)
148133 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)
150146 logger.debug { " Execution result: ${executionResult.result} " }
151147 logger.debug { " Seed score = $seedScore " }
152148 } catch (e: Throwable ) {
@@ -161,38 +157,48 @@ class GreyBoxFuzzer(
161157 }
162158 }
163159
164- private suspend fun exploitationStage (
165- methodLinesToCover : Set <Int >,
166- prevMethodCoverage : Set <Int >
167- ) {
160+ private suspend fun exploitationStage () {
168161 logger.debug { " Exploitation began" }
162+ if (seeds.seedsSize() == 0 ) return
163+ if (seeds.all { it.parameters.isEmpty() }) return
169164 val startTime = System .currentTimeMillis()
170165 val endTime = startTime + timeBudgetInMillis / percentageOfTimeBudgetToChangeMode
171166 var iterationNumber = 0
172167 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 " }
175172 iterationNumber++
176- if (isMethodCovered(methodLinesToCover)) return
177- val randomSeed = seeds.getRandomWeightedSeed() ? : continue
173+ val randomSeed = seeds.getRandomWeightedSeed()
178174 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+ }
184185 logger.debug { " Mutated params = ${mutatedSeed.parameters} " }
185186 val stateBefore = mutatedSeed.createEnvironmentModels()
186187 try {
187188 val executionResult = execute(stateBefore, methodUnderTest)
188189 logger.debug { " Execution result: $executionResult " }
189- val seedScore =
190- handleCoverage(
191- executionResult,
192- prevMethodCoverage,
193- methodLinesToCover
194- )
190+ val seedScore = getCoverage(executionResult)
195191 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+ }
196202 seeds.addSeed(mutatedSeed)
197203 logger.debug { " Execution result: ${executionResult.result} " }
198204 logger.debug { " Seed score = $seedScore " }
@@ -203,27 +209,25 @@ class GreyBoxFuzzer(
203209 }
204210 }
205211
206- private fun handleCoverage (
207- executionResult : UtFuzzingConcreteExecutionResult ,
208- prevMethodCoverage : Set <Int >,
209- currentMethodLines : Set <Int >
212+ private fun getCoverage (
213+ executionResult : UtFuzzingConcreteExecutionResult
210214 ): Set <Int > {
211215 val currentMethodCoverage = executionResult.coverage.coveredInstructions
212216 .asSequence()
213217 .filter { it.methodSignature == methodUnderTest.signature }
214218 .map { it.lineNumber }
215- .filter { it in currentMethodLines }
219+ .filter { it in methodLines }
216220 .toSet()
217- logger.debug { " Covered lines $currentMethodCoverage from $currentMethodLines " }
221+ logger.debug { " Covered lines $currentMethodCoverage from $methodLines " }
218222 executionResult.coverage.coveredInstructions.forEach { CoverageCollector .coverage.add(it) }
219223 return currentMethodCoverage
220224 }
221225
222- private fun isMethodCovered (methodLinesToCover : Set < Int > ): Boolean {
226+ private fun isMethodCovered (): Boolean {
223227 val coveredLines =
224228 CoverageCollector .coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.lineNumber }
225229 .toSet()
226- return coveredLines.containsAll(methodLinesToCover )
230+ return coveredLines.containsAll(methodLines )
227231 }
228232
229233 private suspend fun ConcreteExecutor <UtFuzzingConcreteExecutionResult , UtFuzzingExecutionInstrumentation >.executeConcretely (
0 commit comments