Skip to content

Commit

Permalink
Fix JaCoCo for Contest Estimator (#2373)
Browse files Browse the repository at this point in the history
  • Loading branch information
Markoutte authored Jul 17, 2023
1 parent f44dd6f commit 19fc16c
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
*/
var fuzzingTimeoutInMillis: Long by getLongProperty(3_000L, 0, Long.MAX_VALUE)

/**
* Find implementations of interfaces and abstract classes to fuzz.
*/
var fuzzingImplementationOfAbstractClasses: Boolean by getBooleanProperty(true)

/**
* Generate tests that treat possible overflows in arithmetic operations as errors
* that throw Arithmetic Exception.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,8 @@ val Type.classId: ClassId
else -> error("Unknown type $this")
}

private val logger = KotlinLogging.logger {}

/**
* Class id. Contains name, not a full qualified name.
*
Expand All @@ -905,7 +907,9 @@ open class ClassId @JvmOverloads constructor(
get() = jClass.modifiers

open val canonicalName: String
get() = jClass.canonicalName ?: error("ClassId $name does not have canonical name")
get() = jClass.canonicalName ?: name.also {
logger.error("ClassId $name does not have canonical name")
}

open val simpleName: String get() = jClass.simpleName

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ package org.utbot.fuzzer

import mu.KotlinLogging
import org.utbot.framework.plugin.api.classId
import org.utbot.framework.plugin.api.util.booleanClassId
import org.utbot.framework.plugin.api.util.byteClassId
import org.utbot.framework.plugin.api.util.charClassId
import org.utbot.framework.plugin.api.util.doubleClassId
import org.utbot.framework.plugin.api.util.floatClassId
import org.utbot.framework.plugin.api.util.intClassId
import org.utbot.framework.plugin.api.util.longClassId
import org.utbot.framework.plugin.api.util.shortClassId
import org.utbot.framework.plugin.api.util.stringClassId
import org.utbot.framework.plugin.api.util.*
import org.utbot.framework.util.executableId
import soot.BooleanType
import soot.ByteType
Expand All @@ -28,23 +20,7 @@ import soot.jimple.Constant
import soot.jimple.IntConstant
import soot.jimple.InvokeExpr
import soot.jimple.NullConstant
import soot.jimple.internal.AbstractSwitchStmt
import soot.jimple.internal.ImmediateBox
import soot.jimple.internal.JAssignStmt
import soot.jimple.internal.JCastExpr
import soot.jimple.internal.JEqExpr
import soot.jimple.internal.JGeExpr
import soot.jimple.internal.JGtExpr
import soot.jimple.internal.JIfStmt
import soot.jimple.internal.JInvokeStmt
import soot.jimple.internal.JLeExpr
import soot.jimple.internal.JLookupSwitchStmt
import soot.jimple.internal.JLtExpr
import soot.jimple.internal.JNeExpr
import soot.jimple.internal.JSpecialInvokeExpr
import soot.jimple.internal.JStaticInvokeExpr
import soot.jimple.internal.JTableSwitchStmt
import soot.jimple.internal.JVirtualInvokeExpr
import soot.jimple.internal.*
import soot.toolkits.graph.ExceptionalUnitGraph

private val logger = KotlinLogging.logger {}
Expand Down
20 changes: 14 additions & 6 deletions utbot-fuzzing/src/main/kotlin/org/utbot/fuzzing/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.utbot.fuzzing.seeds.KnownValue
import org.utbot.fuzzing.utils.MissedSeed
import org.utbot.fuzzing.utils.chooseOne
import org.utbot.fuzzing.utils.flipCoin
import org.utbot.fuzzing.utils.transformIfNotEmpty
import kotlin.random.Random

private val logger by lazy { KotlinLogging.logger {} }
Expand Down Expand Up @@ -288,7 +289,14 @@ private object EmptyFeedback : Feedback<Nothing, Nothing> {
class NoSeedValueException internal constructor(
// this type cannot be generalized because Java forbids types for [Throwable].
val type: Any?
) : Exception("No seed candidates generated for type: $type")
) : Exception() {
override fun fillInStackTrace(): Throwable {
return this
}

override val message: String
get() = "No seed candidates generated for type: $type"
}

suspend fun <T, R, D : Description<T>, F : Feedback<T, R>> Fuzzing<T, R, D, F>.fuzz(
description: D,
Expand Down Expand Up @@ -515,11 +523,11 @@ private fun <TYPE, RESULT, DESCRIPTION : Description<TYPE>, FEEDBACK : Feedback<
}
),
modify = task.modify
// .toMutableList()
// .transformIfNotEmpty {
// shuffle(random)
// take(random.nextInt(size + 1))
// }
.toMutableList()
.transformIfNotEmpty {
shuffle(random)
take(configuration.maxNumberOfRecursiveSeedModifications)
}
.mapTo(arrayListOf()) { routine ->
fuzz(
routine.types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,9 @@ data class Configuration(
* to generate a recursive object, but will use [Seed.Recursive.empty] instead.
*/
var generateEmptyRecursiveForMissedTypes: Boolean = true,

/**
* Limits maximum number of recursive seed modifications
*/
var maxNumberOfRecursiveSeedModifications: Int = 10,
)
61 changes: 39 additions & 22 deletions utbot-fuzzing/src/main/kotlin/org/utbot/fuzzing/Providers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ fun interface ValueProvider<T, R, D : Description<T>> {
*/
fun except(filter: (ValueProvider<T, R, D>) -> Boolean): ValueProvider<T, R, D> {
return if (this is Combined) {
Combined(providers.filterNot(filter))
Combined(providers.map { it.unwrapIfFallback() }.filterNot(filter))
} else {
Combined(if (filter(this)) emptyList() else listOf(this))
Combined(if (filter(unwrapIfFallback())) emptyList() else listOf(this))
}
}

Expand All @@ -117,26 +117,7 @@ fun interface ValueProvider<T, R, D : Description<T>> {
* Uses fallback value provider in case when 'this' one failed to generate any value.
*/
fun withFallback(fallback: ValueProvider<T, R, D>) : ValueProvider<T, R, D> {
val thisProvider = this
return object : ValueProvider<T, R, D> {
override fun enrich(description: D, type: T, scope: Scope) {
thisProvider.enrich(description, type, scope)
// Enriching scope by fallback value provider in this point is not quite right,
// but it doesn't look as a problem right now.
fallback.enrich(description, type, scope)
}

override fun generate(description: D, type: T): Sequence<Seed<T, R>> {
val default = if (thisProvider.accept(type)) thisProvider.generate(description, type) else emptySequence()
return if (default.iterator().hasNext()) {
default
} else if (fallback.accept(type)) {
fallback.generate(description, type)
} else {
emptySequence()
}
}
}
return Fallback(this, fallback)
}

/**
Expand All @@ -152,6 +133,42 @@ fun interface ValueProvider<T, R, D : Description<T>> {
return if (flag) block(this) else this
}

/**
* Checks if current provider has fallback and return the initial provider.
*
* If the initial provider is also fallback, then it is unwrapped too.
*
* @return unwrapped provider or this if it is not fallback
*/
fun unwrapIfFallback(): ValueProvider<T, R, D> {
return if (this is Fallback<T, R, D>) { provider.unwrapIfFallback() } else { this }
}

private class Fallback<T, R, D : Description<T>>(
val provider: ValueProvider<T, R, D>,
val fallback: ValueProvider<T, R, D>,
): ValueProvider<T, R, D> {

override fun enrich(description: D, type: T, scope: Scope) {
provider.enrich(description, type, scope)
// Enriching scope by fallback value provider in this point is not quite right,
// but it doesn't look as a problem right now.
fallback.enrich(description, type, scope)
}

override fun generate(description: D, type: T): Sequence<Seed<T, R>> {
val default = if (provider.accept(type)) provider.generate(description, type) else emptySequence()
return if (default.iterator().hasNext()) {
default
} else if (fallback.accept(type)) {
fallback.generate(description, type)
} else {
emptySequence()
}
}

}

/**
* Wrapper class that delegates implementation to the [providers].
*/
Expand Down
21 changes: 21 additions & 0 deletions utbot-fuzzing/src/test/kotlin/org/utbot/fuzzing/ProvidersTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,27 @@ class ProvidersTest {
Assertions.assertEquals(3, (seq.drop(1).first() as Seed.Simple).value)
}

@Test
fun `test fallback unwrapping from providers`() {
val provider1 = p { 2 }
val provider2 = p { 3 }
val fallback = p { 4 }
val providers1 = ValueProvider.of(listOf(
provider1.withFallback(fallback),
provider2
))
val seq1 = providers1.generate(description, Unit).toSet()
Assertions.assertEquals(2, seq1.count())
Assertions.assertEquals(2, (seq1.first() as Seed.Simple).value)
Assertions.assertEquals(3, (seq1.drop(1).first() as Seed.Simple).value)

val providers2 = providers1.except(provider1)

val seq2 = providers2.generate(description, Unit).toSet()
Assertions.assertEquals(1, seq2.count())
Assertions.assertEquals(3, (seq2.first() as Seed.Simple).value)
}

@Test
fun `provider is not called when accept-method returns false`() {
val seq = ValueProvider.of(listOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.utbot.fuzzing

import mu.KotlinLogging
import org.utbot.framework.UtSettings
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.api.Instruction
Expand Down Expand Up @@ -42,7 +43,9 @@ fun defaultValueProviders(idGenerator: IdentityPreservingIdGenerator<Int>) = lis
FloatValueProvider,
StringValueProvider,
NumberValueProvider,
ObjectValueProvider(idGenerator),
ObjectValueProvider(idGenerator).letIf(UtSettings.fuzzingImplementationOfAbstractClasses) { ovp ->
ovp.withFallback(AbstractsObjectValueProvider(idGenerator))
},
ArrayValueProvider(idGenerator),
EnumValueProvider(idGenerator),
ListSetValueProvider(idGenerator),
Expand Down
Loading

0 comments on commit 19fc16c

Please sign in to comment.