Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniilStepanov committed Jan 24, 2023
1 parent 554a9c9 commit 04fe674
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class GreyBoxFuzzer(
private val timeOfStart = System.currentTimeMillis()
private val percentageOfTimeBudgetToChangeMode = 25
private val logger = KotlinLogging.logger {}
private val classMutator = Mutator()

init {
GenericsInfoFactory.disableCache()
Expand Down Expand Up @@ -97,7 +98,7 @@ class GreyBoxFuzzer(
regenerateThis = false
} else if (Random.getTrue(60)) {
logger.debug { "Trying to mutate this instance" }
thisInstancesHistory += Mutator.mutateThisInstance(
thisInstancesHistory += classMutator.mutateThisInstance(
thisInstancesHistory.last(),
classFieldsUsedByFunc.toList(),
generatorContext
Expand Down Expand Up @@ -207,7 +208,7 @@ class GreyBoxFuzzer(
val randomSeed = seeds.getRandomWeightedSeed()
logger.debug { "Random seed params = ${randomSeed.parameters}" }
val mutatedSeed =
Mutator.mutateSeed(
classMutator.mutateSeed(
randomSeed,
GreyBoxFuzzerGeneratorsAndSettings.sourceOfRandomness,
GreyBoxFuzzerGeneratorsAndSettings.genStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object DataGenerator {
): UtModel {
val classId = parameterTypeContext.rawClass.id
logger.debug { "Trying to generate UtModel of type ${classId.name} 3 times" }
var generatedInstance: UtModel? = null
var generatedInstance: UtModel?
repeat(3) {
generatedInstance =
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
val resolvedJavaType = parameterTypeContext!!.generics.resolveType(parameterTypeContext!!.type())
val gctx = resolvedJavaType.createGenericsContext(clazz!!)
if (clazz == randomFieldDeclaringClass) {
return Mutator.regenerateFieldWithContext(gctx, cachedUtModel, randomField, generatorContext)?.let {
return Mutator().regenerateFieldWithContext(gctx, cachedUtModel, randomField, generatorContext)?.let {
mutatedFields[randomField] = it.second
it.first
} ?: cachedUtModel
Expand All @@ -184,7 +184,7 @@ class UserClassGenerator : ComponentizedGenerator(Any::class.java) {
clazz!!,
chain.map { it!! }.reversed().drop(1)
) ?: return cachedUtModel
return Mutator.regenerateFieldWithContext(genericsContext, cachedUtModel, randomField, generatorContext)
return Mutator().regenerateFieldWithContext(genericsContext, cachedUtModel, randomField, generatorContext)
?.let {
mutatedFields[randomField] = it.second
it.first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
package org.utbot.greyboxfuzzer.generator.userclasses.generator

import org.utbot.common.isAbstract
import org.utbot.greyboxfuzzer.generator.DataGenerator
import org.utbot.greyboxfuzzer.generator.QuickCheckExtensions
import org.utbot.greyboxfuzzer.util.*
import org.utbot.greyboxfuzzer.util.logger
import org.utbot.framework.plugin.api.*
import org.utbot.framework.plugin.api.util.executableId
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.objectClassId
import org.utbot.greyboxfuzzer.generator.GreyBoxFuzzerGeneratorsAndSettings.generatorRepository
import org.utbot.greyboxfuzzer.generator.getOrProduceGenerator
import org.utbot.greyboxfuzzer.generator.userclasses.UserClassGenerator
import org.utbot.greyboxfuzzer.quickcheck.generator.GenerationStatus
import org.utbot.greyboxfuzzer.quickcheck.generator.GeneratorContext
import org.utbot.greyboxfuzzer.quickcheck.internal.ParameterTypeContext
Expand All @@ -30,6 +32,9 @@ class InterfaceImplementationsInstanceGenerator(
override fun generate(): UtModel {
//Try to generate with statics with some probability
val clazz = resolvedType.toClass() ?: return UtNullModel(objectClassId)
if (clazz.name.contains("HttpOutputMessage")) {
println()
}
if (Random.getTrue(50)) {
try {
StaticsBasedInstanceGenerator(
Expand All @@ -47,10 +52,20 @@ class InterfaceImplementationsInstanceGenerator(
}
}
val genericsContext =
QuickCheckExtensions.getRandomImplementerGenericContext(clazz, resolvedType)// ?: return UtNullModel(clazz.id)
if (genericsContext == null || Random.getTrue(30)) {
return generateMock(clazz, resolvedType, typeContext, generatorContext)
QuickCheckExtensions.getRandomImplementerGenericContext(
clazz,
resolvedType
)// ?: return UtNullModel(clazz.id)
logger.debug { "Implementer of ${clazz.name}! It is a ${genericsContext?.currentClass()?.name}" }
if (genericsContext == null || Random.getTrue(5)) {
logger.debug { "Generate mock anyway" }
return try {
generateMock(clazz, resolvedType, typeContext, generatorContext)
} catch (e: Throwable) {
UtNullModel(clazz.id)
}
}
logger.debug { "Trying to generate implementer ${genericsContext.currentClass().name}" }
val resUtModel =
ClassesInstanceGenerator(
genericsContext.currentClass(),
Expand Down Expand Up @@ -79,13 +94,22 @@ class InterfaceImplementationsInstanceGenerator(
)
else -> resUtModel
}
.let {
if (it is UtNullModel && Random.getTrue(50)) generateMock(
clazz,
resolvedType,
typeContext,
generatorContext
) else it
.let {
if (it is UtNullModel && Random.getTrue(50)) {
try {
generateMock(
clazz,
resolvedType,
typeContext,
generatorContext
)
}catch (e: Throwable) {
it
}
}
else {
it
}
}
}

Expand All @@ -95,33 +119,45 @@ class InterfaceImplementationsInstanceGenerator(
typeContext: GenericsContext,
generatorContext: GeneratorContext
): UtModel {
logger.debug { "Mock generation" }
if (!clazz.isInterface) return UtNullModel(clazz.id)
val sootClazz = clazz.toSootClass() ?: return UtNullModel(clazz.id)
val constructor = generatorContext.utModelConstructor
val allNeededInterfaces = clazz.methods.map { it.declaringClass }.filter { it != clazz }.toSet()
val chainToGenericsContext = allNeededInterfaces.map { cl ->
val chain = cl.toSootClass()
?.getImplementersOfWithChain()
?.filter { it.contains(sootClazz) }
?.map { it.dropLastWhile { it != sootClazz } }
?.minByOrNull { it.size }
?.map { it.toJavaClass() }
if (chain == null || chain.any { it == null }) {
null
} else {
cl to QuickCheckExtensions.buildGenericsContextForInterfaceParent(
resolvedType,
clazz,
chain.map { it!! }.reversed().drop(1)
)
}
}
val allChainToGenericsContext = chainToGenericsContext + (clazz to typeContext)
val allChainToGenericsContext = allNeededInterfaces.map { it to ParameterTypeContext.forClass(it).generics } + (clazz to typeContext)
// if (allNeededInterfaces.all { it.typeParameters.isEmpty() }) {
// allNeededInterfaces.map { it to ParameterTypeContext.forType(it).generics }
// } else {
// //TODO debug this
// val chainToGenericsContext = allNeededInterfaces.map { cl ->
// val chain = cl.toSootClass()
// ?.getImplementersOfWithChain(onlyConcreteClasses = false, allowNotOnlyStdLib = true)
// ?.filter { it.contains(sootClazz) }
// ?.map { it.dropLastWhile { it != sootClazz } }
// ?.minByOrNull { it.size }
// ?.map { it.toJavaClass() }
// if (chain == null || chain.any { it == null }) {
// null
// } else {
// cl to QuickCheckExtensions.buildGenericsContextForInterfaceParent(
// resolvedType,
// clazz,
// chain.map { it!! }.reversed().drop(1)
// )
// }
// }
// chainToGenericsContext + (clazz to typeContext)
// }
//val allChainToGenericsContext = chainToGenericsContext + (clazz to typeContext)
val mocks = clazz.methods
.filter { it.isAbstract }
.associateTo(mutableMapOf()) { method ->
val genericsContextForMethod =
allChainToGenericsContext.find { it!!.first == method.declaringClass }?.second
try {
allChainToGenericsContext.find { it!!.first == method.declaringClass }?.second
} catch (e: Throwable) {
null
}
val methodReturnType =
if (genericsContextForMethod != null) {
genericsContextForMethod.method(method).resolveReturnType().let {
Expand All @@ -133,13 +169,7 @@ class InterfaceImplementationsInstanceGenerator(
val parameterTypeContext = ParameterTypeContext.forType(methodReturnType, genericsContextForMethod)
val generatedUtModelWithReturnType =
try {
DataGenerator.generateUtModel(
parameterTypeContext,
depth,
generatorContext,
sourceOfRandomness,
generationStatus
)
generateUtModelForMock(parameterTypeContext, depth, generatorContext, sourceOfRandomness, generationStatus)
} catch (_: Throwable) {
UtNullModel(methodReturnType.toClass()!!.id)
}
Expand All @@ -148,6 +178,34 @@ class InterfaceImplementationsInstanceGenerator(
return UtCompositeModel(constructor.computeUnusedIdAndUpdate(), clazz.id, isMock = true, mocks = mocks)
}

private fun generateUtModelForMock(
parameterTypeContext: ParameterTypeContext,
depth: Int = 0,
generatorContext: GeneratorContext,
random: SourceOfRandomness,
status: GenerationStatus
): UtModel {
val classId = parameterTypeContext.rawClass.id
logger.debug { "Trying to generate UtModel of type ${classId.name} 3 times" }
if (parameterTypeContext.getAllSubParameterTypeContexts(sourceOfRandomness).any { it.rawClass.isInterface }) {
return UtNullModel(classId)
}
var generatedInstance: UtModel?
repeat(3) {
generatedInstance =
try {
val generator =
generatorRepository.getOrProduceGenerator(parameterTypeContext, generatorContext, depth)
?: return@repeat
generator.generateImpl(random, status)
} catch (_: Throwable) {
null
}
generatedInstance?.let { if (it !is UtNullModel) return it }
}
return UtNullModel(classId)
}

// private fun buildGenericsContextForInterfaceParent(resolvedType: Type, clazz: Class<*>, parentChain: List<Class<*>>): GenericsContext? {
// val generics = mutableListOf<Pair<Type, MutableList<Type>>>()
// var curClass = clazz
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import java.lang.reflect.Field
import java.lang.reflect.Modifier
import kotlin.random.Random

object Mutator {
class Mutator {

fun mutateSeed(seed: Seed, sourceOfRandomness: SourceOfRandomness, genStatus: GenerationStatus): Seed {
val seedCopy = seed.copy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,17 @@ val ParameterizedTypeImpl.actualTypeArgumentsRecursive: List<Type>
return res
}

fun Class<*>.isFromSameJar(other: Class<*>) =
try {
val thisJar =
this.getResource('/' + this.name.replace('.', '/') + ".class")?.path?.substringBefore(".jar!") ?: "1"
val otherJar =
other.getResource('/' + other.name.replace('.', '/') + ".class")?.path?.substringBefore(".jar!") ?: "2"
thisJar == otherJar
} catch (e: Throwable) {
false
}


//fun Parameter.replaceUnresolvedGenericsToRandomTypes() {
// val allUnresolvedTypesInType = (this.parameterizedType as? ParameterizedTypeImpl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,28 @@ import java.lang.reflect.Method
import kotlin.reflect.KFunction
import kotlin.reflect.jvm.javaMethod

fun SootClass.getImplementersOfWithChain(): List<List<SootClass>> {
fun SootClass.getImplementersOfWithChain(onlyConcreteClasses: Boolean = true, allowNotOnlyStdLib: Boolean = false): List<List<SootClass>> {
this.checkLevel(SootClass.HIERARCHY)
// if (!this.isInterface && !this.isAbstract) {
// throw RuntimeException("interfaced needed; got $this")
// }
val hierarchy = Hierarchy()
val thisAsJavaClass = this.toJavaClass() ?: return emptyList()
val res = mutableListOf(mutableListOf(this))
val queue = ArrayDeque<SootClass>()
queue.add(this)
while (queue.isNotEmpty()) {
val curSootClass = queue.removeFirst()
val implementers =
if (curSootClass.isInterface) {
hierarchy.getDirectImplementersOf(curSootClass)
.filter { it.interfaces.contains(curSootClass) } + hierarchy.getDirectSubinterfacesOf(curSootClass)
Scene.v().classes.filter { it.interfaces.contains(curSootClass) }
.filter { it.interfaces.contains(curSootClass) } //+ hierarchy.getDirectSubinterfacesOf(curSootClass)
} else {
hierarchy.getDirectSubclassesOf(curSootClass)
Scene.v().classes.filter { it.superclassOrNull == curSootClass }
//hierarchy.getDirectSubclassesOf(curSootClass)
}
if (implementers.isEmpty()) continue
val oldLists = res.removeIfAndReturnRemovedElements { it.last() == curSootClass }
if (curSootClass.isConcrete) {
if (curSootClass.isConcrete || !onlyConcreteClasses) {
oldLists.forEach { res.add(it.toMutableList()) }
}
for (implementer in implementers) {
Expand All @@ -51,12 +52,14 @@ fun SootClass.getImplementersOfWithChain(): List<List<SootClass>> {
}
}
return res.filter {
val isJavaStdLibClass = it.last().javaPackageName.startsWith("java")
val isFromSameProject = it.last().javaPackageName.contains(this.javaPackageName) || this.javaPackageName.contains(it.last().javaPackageName)
val isJavaStdLibClass = it.last().javaPackageName.startsWith("java") || allowNotOnlyStdLib
val isFromSameProject = it.last().toJavaClass()?.isFromSameJar(thisAsJavaClass) ?: false
//it.last().javaPackageName.contains(this.javaPackageName) || this.javaPackageName.contains(it.last().javaPackageName)
val isFromSamePackage = it.last().javaPackageName == this.javaPackageName
val isSupportedPackage = isJavaStdLibClass || isFromSameProject
val isAccessible = it.last().isPublic || (!it.last().isPublic && isFromSamePackage)
it.all { !it.toString().contains("$") } && isAccessible && it.last().isConcrete && isSupportedPackage
val isConcrete = !onlyConcreteClasses || it.last().isConcrete
it.all { !it.toString().contains("$") } && isAccessible && isConcrete && isSupportedPackage
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import org.utbot.framework.codegen.domain.models.CgStatement
import org.utbot.framework.codegen.domain.models.CgSwitchCase
import org.utbot.framework.codegen.domain.models.CgSwitchCaseLabel
import org.utbot.framework.codegen.domain.models.CgTestMethod
import org.utbot.framework.codegen.domain.models.CgMockMethod
import org.utbot.framework.codegen.domain.models.CgThisInstance
import org.utbot.framework.codegen.domain.models.CgTripleSlashMultilineComment
import org.utbot.framework.codegen.domain.models.CgTryCatch
Expand Down Expand Up @@ -310,6 +311,8 @@ internal class CgPythonRenderer(
print(")")
}

override fun renderMethodSignature(element: CgMockMethod): Unit = renderMethodSignature(element)

override fun renderMethodSignature(element: CgErrorTestMethod) {
print("def ")
print(element.name)
Expand Down

0 comments on commit 04fe674

Please sign in to comment.