Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4da0878
merge
DaniilStepanov Nov 9, 2022
9fa553a
mocks generation
DaniilStepanov Nov 15, 2022
390d805
remove shrinker
Saloed Nov 10, 2022
d823f29
Rename .java to .kt
Saloed Nov 10, 2022
1343666
rewrite quickcheck on Kotlin
Saloed Nov 10, 2022
854c790
Rename .java to .kt
DaniilStepanov Nov 15, 2022
4d374c7
this instance rewriting
DaniilStepanov Nov 15, 2022
3157025
Added mutations
DaniilStepanov Nov 22, 2022
14604b4
minor
DaniilStepanov Nov 22, 2022
c5f5ae2
New seed selection strategy and time budget for generation
DaniilStepanov Nov 29, 2022
1dbcde7
refactoring and fixes
DaniilStepanov Dec 1, 2022
3452621
m
DaniilStepanov Dec 1, 2022
8240554
UnsafeBasedInstanceGenerator done
DaniilStepanov Dec 6, 2022
ad5af5d
Mutator refactorings
DaniilStepanov Dec 6, 2022
9e0ac70
minor
DaniilStepanov Dec 6, 2022
09343b0
Contest mode is done
DaniilStepanov Dec 19, 2022
3a86fd6
merge
DaniilStepanov Dec 19, 2022
1de5db5
constants collector
DaniilStepanov Dec 19, 2022
5fb1090
removed unnecessary files
DaniilStepanov Dec 19, 2022
1cc03c3
bug fixes
DaniilStepanov Dec 20, 2022
7eab043
removing fuzzer executor
DaniilStepanov Dec 20, 2022
3018dd7
Global refactorings
DaniilStepanov Dec 28, 2022
2bc68a0
minor
DaniilStepanov Dec 28, 2022
bbb34cd
minor fixes
DaniilStepanov Dec 28, 2022
4f77b79
minor
DaniilStepanov Dec 28, 2022
dd16ada
Fixed nested classes generation
DaniilStepanov Jan 13, 2023
ddaf943
fixes to contest
DaniilStepanov Jan 18, 2023
554a9c9
Mock renderer added
DaniilStepanov Jan 19, 2023
04fe674
fixes
DaniilStepanov Jan 24, 2023
7392e6d
rebase
DaniilStepanov Jan 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Contest mode is done
  • Loading branch information
DaniilStepanov committed Jan 24, 2023
commit 09343b0ee762c86a75bf136b982ff270581d686b
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ sealed class UtExecutionFailure : UtExecutionResult() {
get() = exception
}

data class UtExecutionSuccessConcrete(val result: Any?) : UtExecutionResult() {
override fun toString() = "$result"
}

data class UtOverflowFailure(
override val exception: Throwable,
) : UtExecutionFailure()
Expand Down Expand Up @@ -110,11 +106,9 @@ inline fun UtExecutionResult.onFailure(action: (exception: Throwable) -> Unit):
fun UtExecutionResult.getOrThrow(): UtModel = when (this) {
is UtExecutionSuccess -> model
is UtExecutionFailure -> throw exception
is UtExecutionSuccessConcrete -> UtNullModel(objectClassId)
}

fun UtExecutionResult.exceptionOrNull(): Throwable? = when (this) {
is UtExecutionFailure -> rootCauseException
is UtExecutionSuccess -> null
is UtExecutionSuccessConcrete -> null
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import org.utbot.framework.plugin.api.UtExecution
import org.utbot.framework.plugin.api.UtExecutionFailure
import org.utbot.framework.plugin.api.UtExecutionResult
import org.utbot.framework.plugin.api.UtExecutionSuccess
import org.utbot.framework.plugin.api.UtExecutionSuccessConcrete
import org.utbot.framework.plugin.api.UtLambdaModel
import org.utbot.framework.plugin.api.UtMockValue
import org.utbot.framework.plugin.api.UtModel
Expand Down Expand Up @@ -494,7 +493,6 @@ class ValueConstructor {
private fun <R> UtExecutionResult.map(transform: (model: UtModel) -> R): Result<R> = when (this) {
is UtExecutionSuccess -> Result.success(transform(model))
is UtExecutionFailure -> Result.failure(exception)
is UtExecutionSuccessConcrete -> Result.success(transform(UtNullModel(Any::class.java.id)))
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ class UtBotSymbolicEngine(
}

//Simple fuzzing
fun greyBoxFuzzing(until: Long = Long.MAX_VALUE) =
flow<UtResult> {
fun greyBoxFuzzing(timeBudget: Long = Long.MAX_VALUE) =
flow {
GenericsInfoFactory.disableCache()
val isFuzzable = methodUnderTest.parameters.all { classId ->
classId != Method::class.java.id // causes the child process crash at invocation
Expand All @@ -431,12 +431,14 @@ class UtBotSymbolicEngine(
}

try {
GreyBoxFuzzer(
concreteExecutor.pathsToUserClasses,
concreteExecutor.pathsToDependencyClasses,
methodUnderTest,
120_000L
).fuzz()
emitAll(
GreyBoxFuzzer(
concreteExecutor.pathsToUserClasses,
concreteExecutor.pathsToDependencyClasses,
methodUnderTest,
timeBudget
).fuzz()
)
} catch (e: CancellationException) {
logger.debug { "Cancelled by timeout" }
} catch (e: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.utbot.engine.greyboxfuzzer

import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import org.utbot.engine.*
import org.utbot.engine.greyboxfuzzer.generator.*
import org.utbot.engine.greyboxfuzzer.mutator.Mutator
Expand All @@ -12,8 +14,8 @@ import org.utbot.framework.plugin.api.util.*
import org.utbot.framework.util.sootMethod
import org.utbot.instrumentation.ConcreteExecutor
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
import java.lang.reflect.Executable
import java.lang.reflect.Field
import java.lang.reflect.Method
import kotlin.random.Random

class GreyBoxFuzzer(
Expand All @@ -23,24 +25,19 @@ class GreyBoxFuzzer(
private val timeBudgetInMillis: Long
) {

private val methodLines =
methodUnderTest.sootMethod.activeBody.units
.map { it.javaSourceStartLineNumber }
.filter { it != -1 }
.toSet()
private val seeds = SeedCollector(methodLines = methodLines)
private val succeededExecutions = mutableListOf<UtGreyBoxFuzzedExecution>()
private var methodInstructionsIds: Set<Long>? = null
private var seeds: SeedCollector? = null
private val timeRemain
get() = timeOfStart + timeBudgetInMillis - System.currentTimeMillis()
private val timeOfStart = System.currentTimeMillis()
private val percentageOfTimeBudgetToChangeMode = 10
private val percentageOfTimeBudgetToChangeMode = 25

suspend fun fuzz(): Sequence<UtExecution> {
suspend fun fuzz() = flow {
logger.debug { "Started to fuzz ${methodUnderTest.name}" }
val generatorContext = GeneratorContext()
val javaClazz = methodUnderTest.classId.jClass
val sootMethod = methodUnderTest.sootMethod
val javaMethod = sootMethod.toJavaMethod()!!
val javaMethod = sootMethod.toJavaMethod() ?: return@flow
val classFieldsUsedByFunc = sootMethod.getClassFieldsUsedByFunc(javaClazz)
while (timeRemain > 0 || !isMethodCovered()) {
explorationStage(
Expand All @@ -49,15 +46,14 @@ class GreyBoxFuzzer(
methodUnderTest,
generatorContext
)
logger.debug { "SEEDS AFTER EXPLORATION STAGE = ${seeds.seedsSize()}" }
logger.debug { "SEEDS AFTER EXPLORATION STAGE = ${seeds?.seedsSize()}" }
if (timeRemain < 0 || isMethodCovered()) break
exploitationStage()
}
return succeededExecutions.asSequence()
}

private suspend fun explorationStage(
method: Method,
private suspend fun FlowCollector<UtExecution>.explorationStage(
method: Executable,
classFieldsUsedByFunc: Set<Field>,
methodUnderTest: ExecutableId,
generatorContext: GeneratorContext
Expand Down Expand Up @@ -112,8 +108,8 @@ class GreyBoxFuzzer(
parameter,
index,
generatorContext,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus
)
}
logger.debug { "Generated params = $generatedParameters" }
Expand All @@ -123,23 +119,27 @@ class GreyBoxFuzzer(
try {
logger.debug { "Execution started" }
val executionResult = execute(stateBefore, methodUnderTest)
if (methodInstructionsIds == null) {
methodInstructionsIds = executionResult.methodInstructionsIds
seeds = SeedCollector(methodInstructionsIds = methodInstructionsIds!!)
}
seeds ?: continue
logger.debug { "Execution result: $executionResult" }
val seedCoverage = getCoverage(executionResult)
logger.debug { "Calculating seed score" }
val seedScore = seeds.calcSeedScore(seedCoverage)
val seedScore = seeds!!.calcSeedScore(seedCoverage)
logger.debug { "Adding seed" }
val seed = Seed(thisInstance, generatedParameters, seedCoverage, seedScore)
if (seeds.isSeedOpensNewCoverage(seed)) {
succeededExecutions.add(
if (seeds!!.isSeedOpensNewCoverage(seed)) {
emit(
UtGreyBoxFuzzedExecution(
stateBefore,
executionResult.result,
coverage = executionResult.coverage,
testMethodName = methodUnderTest.name
executionResult,
coverage = executionResult.coverage
)
)
}
seeds.addSeed(seed)
seeds!!.addSeed(seed)
logger.debug { "Execution result: ${executionResult.result}" }
logger.debug { "Seed score = $seedScore" }
} catch (e: Throwable) {
Expand All @@ -154,10 +154,10 @@ class GreyBoxFuzzer(
}
}

private suspend fun exploitationStage() {
private suspend fun FlowCollector<UtExecution>.exploitationStage() {
logger.debug { "Exploitation began" }
if (seeds.seedsSize() == 0) return
if (seeds.all { it.parameters.isEmpty() }) return
if (seeds == null || seeds!!.seedsSize() == 0) return
if (seeds!!.all { it.parameters.isEmpty() }) return
val startTime = System.currentTimeMillis()
val endTime = startTime + timeBudgetInMillis / percentageOfTimeBudgetToChangeMode
var iterationNumber = 0
Expand All @@ -167,13 +167,13 @@ class GreyBoxFuzzer(
if (iterationNumber > 30_000) return
logger.debug { "Func: ${methodUnderTest.name} Mutation iteration number $iterationNumber" }
iterationNumber++
val randomSeed = seeds.getRandomWeightedSeed()
val randomSeed = seeds!!.getRandomWeightedSeed()
logger.debug { "Random seed params = ${randomSeed.parameters}" }
val mutatedSeed =
Mutator.mutateSeed(
randomSeed,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus
)
if (mutatedSeed == randomSeed) {
logger.debug { "Cant mutate seed" }
Expand All @@ -186,17 +186,16 @@ class GreyBoxFuzzer(
logger.debug { "Execution result: $executionResult" }
val seedScore = getCoverage(executionResult)
mutatedSeed.score = 0.0
if (seeds.isSeedOpensNewCoverage(mutatedSeed)) {
succeededExecutions.add(
if (seeds!!.isSeedOpensNewCoverage(mutatedSeed)) {
emit(
UtGreyBoxFuzzedExecution(
stateBefore,
executionResult.result,
coverage = executionResult.coverage,
testMethodName = methodUnderTest.name
executionResult,
coverage = executionResult.coverage
)
)
}
seeds.addSeed(mutatedSeed)
seeds!!.addSeed(mutatedSeed)
logger.debug { "Execution result: ${executionResult.result}" }
logger.debug { "Seed score = $seedScore" }
} catch (e: Throwable) {
Expand All @@ -208,23 +207,25 @@ class GreyBoxFuzzer(

private fun getCoverage(
executionResult: UtFuzzingConcreteExecutionResult
): Set<Int> {
): Set<Long> {
val currentMethodCoverage = executionResult.coverage.coveredInstructions
.asSequence()
.filter { it.className == methodUnderTest.classId.name.replace('.', '/') }
.filter { it.methodSignature == methodUnderTest.signature }
.map { it.lineNumber }
.filter { it in methodLines }
.map { it.id }
.filter { it in methodInstructionsIds!! }
.toSet()
logger.debug { "Covered lines $currentMethodCoverage from $methodLines" }
executionResult.coverage.coveredInstructions.forEach { CoverageCollector.coverage.add(it) }
logger.debug { "Covered instructions ${currentMethodCoverage.count()} from ${methodInstructionsIds!!.size}" }
executionResult.coverage.coveredInstructions.forEach { CoverageCollector.addCoverage(it) }
return currentMethodCoverage
}

private fun isMethodCovered(): Boolean {
val coveredLines =
CoverageCollector.coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.lineNumber }
methodInstructionsIds ?: return false
val coveredInstructions =
CoverageCollector.coverage.filter { it.methodSignature == methodUnderTest.signature }.map { it.id }
.toSet()
return coveredLines.containsAll(methodLines)
return coveredInstructions.containsAll(methodInstructionsIds!!)
}

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


private fun generateThisInstance(classId: ClassId, generatorContext: GeneratorContext): ThisInstance =
if (!methodUnderTest.isStatic) {
if (!methodUnderTest.isStatic && !methodUnderTest.isConstructor) {
DataGenerator.generateThis(
classId,
generatorContext,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus
)
} else {
StaticMethodThisInstance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtNullModel
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.jClass
import org.utbot.framework.plugin.api.util.objectClassId
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GenerationState
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
import java.lang.reflect.Parameter

object DataGenerator {

private val generatorRepository = GreyBoxFuzzerGenerators.generatorRepository
private val generatorRepository = GreyBoxFuzzerGeneratorsAndSettings.generatorRepository

fun generateUtModel(
parameterTypeContext: ParameterTypeContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.utbot.engine.greyboxfuzzer.quickcheck.random.SourceOfRandomness
import java.util.*
import java.util.concurrent.atomic.AtomicInteger

object GreyBoxFuzzerGenerators {
object GreyBoxFuzzerGeneratorsAndSettings {

const val seed = 42L
val maxDepthOfGeneration = AtomicInteger(5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.utbot.engine.greyboxfuzzer.generator.userclasses.UserClassGenerator
import org.utbot.engine.greyboxfuzzer.util.*
import org.utbot.engine.logger
import org.utbot.engine.rawType
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.ComponentizedGenerator
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.Generator
import org.utbot.engine.greyboxfuzzer.quickcheck.generator.GeneratorContext
import org.utbot.engine.greyboxfuzzer.quickcheck.internal.FakeAnnotatedTypeFactory
Expand Down Expand Up @@ -87,7 +86,7 @@ fun GeneratorRepository.getOrProduceGenerator(
depth: Int
): Generator? {
val producedUserClassesGenerators = mutableListOf<UserClassGenerator>()
parameterTypeContext.getAllSubParameterTypeContexts(GreyBoxFuzzerGenerators.sourceOfRandomness).reversed()
parameterTypeContext.getAllSubParameterTypeContexts(GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness).reversed()
.forEach { typeContext ->
try {
this.produceGenerator(typeContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
if (Random.getTrue(5)) {
return UtNullModel(clazz!!.id)
}
if (depth >= GreyBoxFuzzerGenerators.maxDepthOfGeneration.toInt()) {
logger.debug { "Depth more than maxDepth ${GreyBoxFuzzerGenerators.maxDepthOfGeneration.toInt()}. Return UtNullModel" }
if (depth >= GreyBoxFuzzerGeneratorsAndSettings.maxDepthOfGeneration.toInt()) {
logger.debug { "Depth more than maxDepth ${GreyBoxFuzzerGeneratorsAndSettings.maxDepthOfGeneration.toInt()}. Return UtNullModel" }
return UtNullModel(clazz!!.id)
}
val immutableClazz = clazz!!
Expand All @@ -84,7 +84,7 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
}
val resolvedJavaType = parameterTypeContext!!.generics.resolveType(parameterTypeContext!!.type())
val gctx =
if (resolvedJavaType is Class<*>) {
if (resolvedJavaType is Class<*> && parameterTypeContext!!.generics.genericsInfo.rootClass == immutableClazz) {
parameterTypeContext!!.generics
} else {
resolvedJavaType.createGenericsContext(immutableClazz)
Expand All @@ -93,8 +93,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
return InterfaceImplementationsInstanceGenerator(
resolvedJavaType,
gctx,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus,
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
generatorContext,
depth
).generate()
Expand All @@ -103,8 +103,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
clazz!!,
gctx,
resolvedJavaType,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus,
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
generatorContext,
depth
)
Expand All @@ -116,8 +116,8 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
gctx,
parameterTypeContext!!.generics,
generationMethod,
GreyBoxFuzzerGenerators.sourceOfRandomness,
GreyBoxFuzzerGenerators.genStatus,
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus,
generatorContext,
depth
).generate()
Expand Down
Loading