Skip to content

Commit ffb42ee

Browse files
Contest mode is done
1 parent 2ceb950 commit ffb42ee

File tree

28 files changed

+436
-201
lines changed

28 files changed

+436
-201
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ sealed class UtExecutionFailure : UtExecutionResult() {
2222
get() = exception
2323
}
2424

25-
data class UtExecutionSuccessConcrete(val result: Any?) : UtExecutionResult() {
26-
override fun toString() = "$result"
27-
}
28-
2925
data class UtOverflowFailure(
3026
override val exception: Throwable,
3127
) : UtExecutionFailure()
@@ -110,11 +106,9 @@ inline fun UtExecutionResult.onFailure(action: (exception: Throwable) -> Unit):
110106
fun UtExecutionResult.getOrThrow(): UtModel = when (this) {
111107
is UtExecutionSuccess -> model
112108
is UtExecutionFailure -> throw exception
113-
is UtExecutionSuccessConcrete -> UtNullModel(objectClassId)
114109
}
115110

116111
fun UtExecutionResult.exceptionOrNull(): Throwable? = when (this) {
117112
is UtExecutionFailure -> rootCauseException
118113
is UtExecutionSuccess -> null
119-
is UtExecutionSuccessConcrete -> null
120114
}

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/util/constructor/ValueConstructor.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import org.utbot.framework.plugin.api.UtExecution
2626
import org.utbot.framework.plugin.api.UtExecutionFailure
2727
import org.utbot.framework.plugin.api.UtExecutionResult
2828
import org.utbot.framework.plugin.api.UtExecutionSuccess
29-
import org.utbot.framework.plugin.api.UtExecutionSuccessConcrete
3029
import org.utbot.framework.plugin.api.UtLambdaModel
3130
import org.utbot.framework.plugin.api.UtMockValue
3231
import org.utbot.framework.plugin.api.UtModel
@@ -494,7 +493,6 @@ class ValueConstructor {
494493
private fun <R> UtExecutionResult.map(transform: (model: UtModel) -> R): Result<R> = when (this) {
495494
is UtExecutionSuccess -> Result.success(transform(model))
496495
is UtExecutionFailure -> Result.failure(exception)
497-
is UtExecutionSuccessConcrete -> Result.success(transform(UtNullModel(Any::class.java.id)))
498496
}
499497

500498
/**

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,8 @@ class UtBotSymbolicEngine(
419419
}
420420

421421
//Simple fuzzing
422-
fun greyBoxFuzzing(until: Long = Long.MAX_VALUE) =
423-
flow<UtResult> {
422+
fun greyBoxFuzzing(timeBudget: Long = Long.MAX_VALUE) =
423+
flow {
424424
GenericsInfoFactory.disableCache()
425425
val isFuzzable = methodUnderTest.parameters.all { classId ->
426426
classId != Method::class.java.id // causes the child process crash at invocation
@@ -430,12 +430,14 @@ class UtBotSymbolicEngine(
430430
}
431431

432432
try {
433-
GreyBoxFuzzer(
434-
concreteExecutor.pathsToUserClasses,
435-
concreteExecutor.pathsToDependencyClasses,
436-
methodUnderTest,
437-
120_000L
438-
).fuzz()
433+
emitAll(
434+
GreyBoxFuzzer(
435+
concreteExecutor.pathsToUserClasses,
436+
concreteExecutor.pathsToDependencyClasses,
437+
methodUnderTest,
438+
timeBudget
439+
).fuzz()
440+
)
439441
} catch (e: CancellationException) {
440442
logger.debug { "Cancelled by timeout" }
441443
} catch (e: Throwable) {

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/GreyBoxFuzzer.kt

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.utbot.engine.greyboxfuzzer
22

3+
import kotlinx.coroutines.flow.FlowCollector
4+
import kotlinx.coroutines.flow.flow
35
import org.utbot.engine.*
46
import org.utbot.engine.greyboxfuzzer.generator.*
57
import org.utbot.engine.greyboxfuzzer.mutator.Mutator
@@ -12,8 +14,8 @@ import org.utbot.framework.plugin.api.util.*
1214
import org.utbot.framework.util.sootMethod
1315
import org.utbot.instrumentation.ConcreteExecutor
1416
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
17+
import java.lang.reflect.Executable
1518
import java.lang.reflect.Field
16-
import java.lang.reflect.Method
1719
import kotlin.random.Random
1820

1921
class GreyBoxFuzzer(
@@ -23,24 +25,19 @@ class GreyBoxFuzzer(
2325
private val timeBudgetInMillis: Long
2426
) {
2527

26-
private val methodLines =
27-
methodUnderTest.sootMethod.activeBody.units
28-
.map { it.javaSourceStartLineNumber }
29-
.filter { it != -1 }
30-
.toSet()
31-
private val seeds = SeedCollector(methodLines = methodLines)
32-
private val succeededExecutions = mutableListOf<UtGreyBoxFuzzedExecution>()
28+
private var methodInstructionsIds: Set<Long>? = null
29+
private var seeds: SeedCollector? = null
3330
private val timeRemain
3431
get() = timeOfStart + timeBudgetInMillis - System.currentTimeMillis()
3532
private val timeOfStart = System.currentTimeMillis()
36-
private val percentageOfTimeBudgetToChangeMode = 10
33+
private val percentageOfTimeBudgetToChangeMode = 25
3734

38-
suspend fun fuzz(): Sequence<UtExecution> {
35+
suspend fun fuzz() = flow {
3936
logger.debug { "Started to fuzz ${methodUnderTest.name}" }
4037
val generatorContext = GeneratorContext()
4138
val javaClazz = methodUnderTest.classId.jClass
4239
val sootMethod = methodUnderTest.sootMethod
43-
val javaMethod = sootMethod.toJavaMethod()!!
40+
val javaMethod = sootMethod.toJavaMethod() ?: return@flow
4441
val classFieldsUsedByFunc = sootMethod.getClassFieldsUsedByFunc(javaClazz)
4542
while (timeRemain > 0 || !isMethodCovered()) {
4643
explorationStage(
@@ -49,15 +46,14 @@ class GreyBoxFuzzer(
4946
methodUnderTest,
5047
generatorContext
5148
)
52-
logger.debug { "SEEDS AFTER EXPLORATION STAGE = ${seeds.seedsSize()}" }
49+
logger.debug { "SEEDS AFTER EXPLORATION STAGE = ${seeds?.seedsSize()}" }
5350
if (timeRemain < 0 || isMethodCovered()) break
5451
exploitationStage()
5552
}
56-
return succeededExecutions.asSequence()
5753
}
5854

59-
private suspend fun explorationStage(
60-
method: Method,
55+
private suspend fun FlowCollector<UtExecution>.explorationStage(
56+
method: Executable,
6157
classFieldsUsedByFunc: Set<Field>,
6258
methodUnderTest: ExecutableId,
6359
generatorContext: GeneratorContext
@@ -112,8 +108,8 @@ class GreyBoxFuzzer(
112108
parameter,
113109
index,
114110
generatorContext,
115-
GreyBoxFuzzerGenerators.sourceOfRandomness,
116-
GreyBoxFuzzerGenerators.genStatus
111+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
112+
GreyBoxFuzzerGeneratorsAndSettings.genStatus
117113
)
118114
}
119115
logger.debug { "Generated params = $generatedParameters" }
@@ -123,23 +119,27 @@ class GreyBoxFuzzer(
123119
try {
124120
logger.debug { "Execution started" }
125121
val executionResult = execute(stateBefore, methodUnderTest)
122+
if (methodInstructionsIds == null) {
123+
methodInstructionsIds = executionResult.methodInstructionsIds
124+
seeds = SeedCollector(methodInstructionsIds = methodInstructionsIds!!)
125+
}
126+
seeds ?: continue
126127
logger.debug { "Execution result: $executionResult" }
127128
val seedCoverage = getCoverage(executionResult)
128129
logger.debug { "Calculating seed score" }
129-
val seedScore = seeds.calcSeedScore(seedCoverage)
130+
val seedScore = seeds!!.calcSeedScore(seedCoverage)
130131
logger.debug { "Adding seed" }
131132
val seed = Seed(thisInstance, generatedParameters, seedCoverage, seedScore)
132-
if (seeds.isSeedOpensNewCoverage(seed)) {
133-
succeededExecutions.add(
133+
if (seeds!!.isSeedOpensNewCoverage(seed)) {
134+
emit(
134135
UtGreyBoxFuzzedExecution(
135136
stateBefore,
136-
executionResult.result,
137-
coverage = executionResult.coverage,
138-
testMethodName = methodUnderTest.name
137+
executionResult,
138+
coverage = executionResult.coverage
139139
)
140140
)
141141
}
142-
seeds.addSeed(seed)
142+
seeds!!.addSeed(seed)
143143
logger.debug { "Execution result: ${executionResult.result}" }
144144
logger.debug { "Seed score = $seedScore" }
145145
} catch (e: Throwable) {
@@ -154,10 +154,10 @@ class GreyBoxFuzzer(
154154
}
155155
}
156156

157-
private suspend fun exploitationStage() {
157+
private suspend fun FlowCollector<UtExecution>.exploitationStage() {
158158
logger.debug { "Exploitation began" }
159-
if (seeds.seedsSize() == 0) return
160-
if (seeds.all { it.parameters.isEmpty() }) return
159+
if (seeds == null || seeds!!.seedsSize() == 0) return
160+
if (seeds!!.all { it.parameters.isEmpty() }) return
161161
val startTime = System.currentTimeMillis()
162162
val endTime = startTime + timeBudgetInMillis / percentageOfTimeBudgetToChangeMode
163163
var iterationNumber = 0
@@ -167,13 +167,13 @@ class GreyBoxFuzzer(
167167
if (iterationNumber > 30_000) return
168168
logger.debug { "Func: ${methodUnderTest.name} Mutation iteration number $iterationNumber" }
169169
iterationNumber++
170-
val randomSeed = seeds.getRandomWeightedSeed()
170+
val randomSeed = seeds!!.getRandomWeightedSeed()
171171
logger.debug { "Random seed params = ${randomSeed.parameters}" }
172172
val mutatedSeed =
173173
Mutator.mutateSeed(
174174
randomSeed,
175-
GreyBoxFuzzerGenerators.sourceOfRandomness,
176-
GreyBoxFuzzerGenerators.genStatus
175+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
176+
GreyBoxFuzzerGeneratorsAndSettings.genStatus
177177
)
178178
if (mutatedSeed == randomSeed) {
179179
logger.debug { "Cant mutate seed" }
@@ -186,17 +186,16 @@ class GreyBoxFuzzer(
186186
logger.debug { "Execution result: $executionResult" }
187187
val seedScore = getCoverage(executionResult)
188188
mutatedSeed.score = 0.0
189-
if (seeds.isSeedOpensNewCoverage(mutatedSeed)) {
190-
succeededExecutions.add(
189+
if (seeds!!.isSeedOpensNewCoverage(mutatedSeed)) {
190+
emit(
191191
UtGreyBoxFuzzedExecution(
192192
stateBefore,
193-
executionResult.result,
194-
coverage = executionResult.coverage,
195-
testMethodName = methodUnderTest.name
193+
executionResult,
194+
coverage = executionResult.coverage
196195
)
197196
)
198197
}
199-
seeds.addSeed(mutatedSeed)
198+
seeds!!.addSeed(mutatedSeed)
200199
logger.debug { "Execution result: ${executionResult.result}" }
201200
logger.debug { "Seed score = $seedScore" }
202201
} catch (e: Throwable) {
@@ -208,23 +207,25 @@ class GreyBoxFuzzer(
208207

209208
private fun getCoverage(
210209
executionResult: UtFuzzingConcreteExecutionResult
211-
): Set<Int> {
210+
): Set<Long> {
212211
val currentMethodCoverage = executionResult.coverage.coveredInstructions
213212
.asSequence()
213+
.filter { it.className == methodUnderTest.classId.name.replace('.', '/') }
214214
.filter { it.methodSignature == methodUnderTest.signature }
215-
.map { it.lineNumber }
216-
.filter { it in methodLines }
215+
.map { it.id }
216+
.filter { it in methodInstructionsIds!! }
217217
.toSet()
218-
logger.debug { "Covered lines $currentMethodCoverage from $methodLines" }
219-
executionResult.coverage.coveredInstructions.forEach { CoverageCollector.coverage.add(it) }
218+
logger.debug { "Covered instructions ${currentMethodCoverage.count()} from ${methodInstructionsIds!!.size}" }
219+
executionResult.coverage.coveredInstructions.forEach { CoverageCollector.addCoverage(it) }
220220
return currentMethodCoverage
221221
}
222222

223223
private fun isMethodCovered(): Boolean {
224-
val coveredLines =
225-
CoverageCollector.coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.lineNumber }
224+
methodInstructionsIds ?: return false
225+
val coveredInstructions =
226+
CoverageCollector.coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.id }
226227
.toSet()
227-
return coveredLines.containsAll(methodLines)
228+
return coveredInstructions.containsAll(methodInstructionsIds!!)
228229
}
229230

230231
private suspend fun ConcreteExecutor<UtFuzzingConcreteExecutionResult, UtFuzzingExecutionInstrumentation>.executeConcretely(
@@ -253,12 +254,12 @@ class GreyBoxFuzzer(
253254

254255

255256
private fun generateThisInstance(classId: ClassId, generatorContext: GeneratorContext): ThisInstance =
256-
if (!methodUnderTest.isStatic) {
257+
if (!methodUnderTest.isStatic && !methodUnderTest.isConstructor) {
257258
DataGenerator.generateThis(
258259
classId,
259260
generatorContext,
260-
GreyBoxFuzzerGenerators.sourceOfRandomness,
261-
GreyBoxFuzzerGenerators.genStatus
261+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
262+
GreyBoxFuzzerGeneratorsAndSettings.genStatus
262263
)
263264
} else {
264265
StaticMethodThisInstance

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/DataGenerator.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ import org.utbot.framework.plugin.api.UtModel
1212
import org.utbot.framework.plugin.api.UtNullModel
1313
import org.utbot.framework.plugin.api.util.id
1414
import org.utbot.framework.plugin.api.util.jClass
15-
import org.utbot.framework.plugin.api.util.objectClassId
1615
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GenerationState
1716
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
1817
import java.lang.reflect.Parameter
1918

2019
object DataGenerator {
2120

22-
private val generatorRepository = GreyBoxFuzzerGenerators.generatorRepository
21+
private val generatorRepository = GreyBoxFuzzerGeneratorsAndSettings.generatorRepository
2322

2423
fun generateUtModel(
2524
parameterTypeContext: ParameterTypeContext,

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/GreyBoxFuzzerGenerators.kt renamed to utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/GreyBoxFuzzerGeneratorsAndSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import org.utbot.engine.greyboxfuzzer.quickcheck.random.SourceOfRandomness
1212
import java.util.*
1313
import java.util.concurrent.atomic.AtomicInteger
1414

15-
object GreyBoxFuzzerGenerators {
15+
object GreyBoxFuzzerGeneratorsAndSettings {
1616

1717
const val seed = 42L
1818
val maxDepthOfGeneration = AtomicInteger(5)

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/QuickCheckExtensions.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import org.utbot.engine.greyboxfuzzer.generator.userclasses.UserClassGenerator
1010
import org.utbot.engine.greyboxfuzzer.util.*
1111
import org.utbot.engine.logger
1212
import org.utbot.engine.rawType
13-
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.ComponentizedGenerator
1413
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.Generator
1514
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
1615
import org.utbot.engine.greyboxfuzzer.quickcheck.internal.FakeAnnotatedTypeFactory
@@ -87,7 +86,7 @@ fun GeneratorRepository.getOrProduceGenerator(
8786
depth: Int
8887
): Generator? {
8988
val producedUserClassesGenerators = mutableListOf<UserClassGenerator>()
90-
parameterTypeContext.getAllSubParameterTypeContexts(GreyBoxFuzzerGenerators.sourceOfRandomness).reversed()
89+
parameterTypeContext.getAllSubParameterTypeContexts(GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness).reversed()
9190
.forEach { typeContext ->
9291
try {
9392
this.produceGenerator(typeContext)

utbot-framework/src/main/kotlin/org/utbot/engine/greyboxfuzzer/generator/userclasses/UserClassGenerator.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
6060
if (Random.getTrue(5)) {
6161
return UtNullModel(clazz!!.id)
6262
}
63-
if (depth >= GreyBoxFuzzerGenerators.maxDepthOfGeneration.toInt()) {
64-
logger.debug { "Depth more than maxDepth ${GreyBoxFuzzerGenerators.maxDepthOfGeneration.toInt()}. Return UtNullModel" }
63+
if (depth >= GreyBoxFuzzerGeneratorsAndSettings.maxDepthOfGeneration.toInt()) {
64+
logger.debug { "Depth more than maxDepth ${GreyBoxFuzzerGeneratorsAndSettings.maxDepthOfGeneration.toInt()}. Return UtNullModel" }
6565
return UtNullModel(clazz!!.id)
6666
}
6767
val immutableClazz = clazz!!
@@ -84,7 +84,7 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
8484
}
8585
val resolvedJavaType = parameterTypeContext!!.generics.resolveType(parameterTypeContext!!.type())
8686
val gctx =
87-
if (resolvedJavaType is Class<*>) {
87+
if (resolvedJavaType is Class<*> && parameterTypeContext!!.generics.genericsInfo.rootClass == immutableClazz) {
8888
parameterTypeContext!!.generics
8989
} else {
9090
resolvedJavaType.createGenericsContext(immutableClazz)
@@ -93,8 +93,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
9393
return InterfaceImplementationsInstanceGenerator(
9494
resolvedJavaType,
9595
gctx,
96-
GreyBoxFuzzerGenerators.sourceOfRandomness,
97-
GreyBoxFuzzerGenerators.genStatus,
96+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
97+
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
9898
generatorContext,
9999
depth
100100
).generate()
@@ -103,8 +103,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
103103
clazz!!,
104104
gctx,
105105
resolvedJavaType,
106-
GreyBoxFuzzerGenerators.sourceOfRandomness,
107-
GreyBoxFuzzerGenerators.genStatus,
106+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
107+
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
108108
generatorContext,
109109
depth
110110
)
@@ -116,8 +116,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
116116
gctx,
117117
parameterTypeContext!!.generics,
118118
generationMethod,
119-
GreyBoxFuzzerGenerators.sourceOfRandomness,
120-
GreyBoxFuzzerGenerators.genStatus,
119+
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
120+
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
121121
generatorContext,
122122
depth
123123
).generate()

0 commit comments

Comments
 (0)