Skip to content

Commit

Permalink
Merge branch 'vorpal-research:master' into khbminus/kotlin-metadata-n…
Browse files Browse the repository at this point in the history
…ullability
  • Loading branch information
khbminus authored Aug 6, 2024
2 parents 536fc11 + f2498a6 commit d34b84f
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 48 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Docker images with the latest version installed. Example:

```bash
docker run -v ~/myproject:/home/myproject -v ~/kex-output:/home/kex-output \
abdullin/kex-standalone:0.0.7 --classpath /home/myproject/target/myproject.jar \
abdullin/kex-standalone:0.0.8 --classpath /home/myproject/target/myproject.jar \
--target myproject.\* --output /home/kex-output --mode concolic
```

Expand Down
2 changes: 1 addition & 1 deletion kex-annotation-processor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kex</artifactId>
<groupId>org.vorpal.research</groupId>
<version>0.0.7</version>
<version>0.0.8</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>jar</packaging>
Expand Down
2 changes: 1 addition & 1 deletion kex-boolector/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kex</artifactId>
<groupId>org.vorpal.research</groupId>
<version>0.0.7</version>
<version>0.0.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion kex-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kex</artifactId>
<groupId>org.vorpal.research</groupId>
<version>0.0.7</version>
<version>0.0.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,19 @@ class FinalParameters<T> private constructor(
}
}

inline fun <T : F, U, reified F> FinalParameters<T>.map(transform: (F) -> U): FinalParameters<U> = FinalParameters(
if (instance is F) transform(instance) else null,
args.map(transform),
if (returnValueUnsafe is F) transform(returnValueUnsafe) else null,
)
inline fun <T : F, U, reified F> FinalParameters<T>.map(transform: (F) -> U): FinalParameters<U> = when {
this.isSuccess -> FinalParameters(
if (instance is F) transform(instance) else null,
args.map(transform),
if (returnValueUnsafe is F) transform(returnValueUnsafe) else null,
)

else -> FinalParameters(
if (instance is F) transform(instance) else null,
args.map(transform),
exceptionType
)
}

val <T> FinalParameters<T>?.isSuccessOrFalse: Boolean get() = this?.isSuccess ?: false
val <T> FinalParameters<T>?.isExceptionOrFalse: Boolean get() = this?.isException ?: false
Expand Down
2 changes: 1 addition & 1 deletion kex-executor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.vorpal.research</groupId>
<artifactId>kex</artifactId>
<version>0.0.7</version>
<version>0.0.8</version>
</parent>
<artifactId>kex-executor</artifactId>
<packaging>jar</packaging>
Expand Down
2 changes: 1 addition & 1 deletion kex-ksmt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kex</artifactId>
<groupId>org.vorpal.research</groupId>
<version>0.0.7</version>
<version>0.0.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion kex-runner/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>kex</artifactId>
<groupId>org.vorpal.research</groupId>
<version>0.0.7</version>
<version>0.0.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package org.vorpal.research.kex.jacoco

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.vorpal.research.kthelper.assert.unreachable
import org.vorpal.research.kthelper.logging.log


interface CoverageInfo {
@Serializable
sealed interface CoverageInfo {
val covered: Int
val total: Int
val ratio: Double
}

@Serializable
enum class CoverageUnit(unit: String) {
INSTRUCTION("instructions"),
BRANCH("branches"),
Expand All @@ -33,6 +36,7 @@ enum class CoverageUnit(unit: String) {
}
}

@Serializable
enum class AnalysisUnit(unit: String) {
METHOD("method"),
CLASS("class"),
Expand All @@ -54,6 +58,8 @@ enum class AnalysisUnit(unit: String) {
}
}

@Serializable
@SerialName("genericCoverage")
data class GenericCoverageInfo(
override val covered: Int,
override val total: Int,
Expand All @@ -74,7 +80,8 @@ data class GenericCoverageInfo(
}
}

abstract class CommonCoverageInfo(
@Serializable
sealed class CommonCoverageInfo(
val name: String,
val level: AnalysisUnit,
val instructionCoverage: CoverageInfo,
Expand Down Expand Up @@ -103,7 +110,8 @@ abstract class CommonCoverageInfo(
return name.hashCode()
}
}

@Serializable(with = MethodCoverageInfoSerializer::class)
@SerialName("method")
class MethodCoverageInfo(
name: String,
instructionCoverage: CoverageInfo,
Expand All @@ -119,6 +127,8 @@ class MethodCoverageInfo(
complexityCoverage
)

@Serializable(with = ClassCoverageInfoSerializer::class)
@SerialName("class")
class ClassCoverageInfo(
name: String,
instructionCoverage: CoverageInfo,
Expand Down Expand Up @@ -146,6 +156,8 @@ class ClassCoverageInfo(
}
}

@Serializable(with = PackageCoverageInfoSerializer::class)
@SerialName("package")
class PackageCoverageInfo(
name: String,
instructionCoverage: CoverageInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

package org.vorpal.research.kex.jacoco

import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.jacoco.core.analysis.Analyzer
import org.jacoco.core.analysis.CoverageBuilder
import org.jacoco.core.analysis.ICounter
Expand All @@ -13,7 +15,6 @@ import org.jacoco.core.instr.Instrumenter
import org.jacoco.core.internal.analysis.PackageCoverageImpl
import org.jacoco.core.runtime.LoggerRuntime
import org.jacoco.core.runtime.RuntimeData
import org.junit.runner.Result
import org.vorpal.research.kex.config.kexConfig
import org.vorpal.research.kex.jacoco.minimization.GreedyTestReductionImpl
import org.vorpal.research.kex.jacoco.minimization.TestwiseCoverageReporter
Expand All @@ -28,6 +29,7 @@ import org.vorpal.research.kex.util.asArray
import org.vorpal.research.kex.util.asmString
import org.vorpal.research.kex.util.compiledCodeDirectory
import org.vorpal.research.kex.util.deleteOnExit
import org.vorpal.research.kex.util.getFieldByName
import org.vorpal.research.kex.util.javaString
import org.vorpal.research.kex.util.outputDirectory
import org.vorpal.research.kfg.ClassManager
Expand All @@ -36,19 +38,16 @@ import org.vorpal.research.kfg.container.Container
import org.vorpal.research.kfg.ir.Method
import org.vorpal.research.kthelper.assert.ktassert
import org.vorpal.research.kthelper.assert.unreachable
import org.vorpal.research.kthelper.logging.debug
import org.vorpal.research.kthelper.logging.log
import org.vorpal.research.kthelper.tryOrNull
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.attribute.BasicFileAttributes
import java.util.*
import kotlin.io.path.inputStream
import kotlin.io.path.name
import kotlin.io.path.readBytes
import kotlin.io.path.relativeTo
import kotlin.io.path.writeBytes
import kotlin.streams.toList
import java.util.stream.Collectors
import kotlin.io.path.*
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
Expand Down Expand Up @@ -91,7 +90,7 @@ open class CoverageReporter(
}.also {
deleteOnExit(it)
}
val allTestClasses: Set<Path> by lazy { Files.walk(compileDir).filter { it.isClass }.toList().toSet() }
val allTestClasses: Set<Path> by lazy { Files.walk(compileDir).filter { it.isClass }.collect(Collectors.toSet()) }
protected val compileDir = kexConfig.compiledCodeDirectory
protected lateinit var coverageContext: CoverageContext
protected lateinit var executionData: Map<Path, ExecutionDataStore>
Expand All @@ -107,7 +106,7 @@ open class CoverageReporter(
open fun computeCoverage(
analysisLevel: AnalysisLevel,
testClasses: Set<Path> = this.allTestClasses
): CommonCoverageInfo {
): Set<CommonCoverageInfo> {
ktassert(this.allTestClasses.containsAll(testClasses)) {
log.error("Unexpected set of test classes")
}
Expand All @@ -116,9 +115,9 @@ open class CoverageReporter(
val coverageBuilder = getCoverageBuilderAndCleanup(classes, testClasses)

return when (analysisLevel) {
is PackageLevel -> getPackageCoverage(analysisLevel.pkg, cm, coverageBuilder)
is ClassLevel -> getClassCoverage(cm, coverageBuilder).first()
is MethodLevel -> getMethodCoverage(coverageBuilder, analysisLevel.method)!!
is PackageLevel -> setOf(getPackageCoverage(analysisLevel.pkg, cm, coverageBuilder))
is ClassLevel -> getClassCoverage(cm, coverageBuilder)
is MethodLevel -> setOf(getMethodCoverage(coverageBuilder, analysisLevel.method)!!)
}
}

Expand Down Expand Up @@ -155,11 +154,22 @@ open class CoverageReporter(
is PackageLevel -> Files.walk(jacocoInstrumentedDir)
.filter { it.isClass }
.filter { analysisLevel.pkg.isParent(it.fullyQualifiedName(jacocoInstrumentedDir).asmString) }
.toList()
.collect(Collectors.toList())

is ClassLevel -> {
val klass = analysisLevel.klass.fullName.replace(Package.SEPARATOR, File.separatorChar)
listOf(jacocoInstrumentedDir.resolve("$klass.class"))
val additionalValues = kexConfig
.getStringValue("kex", "collectAdditionalCoverage")
?.split(",")
?.map { Package.parse(it.trim().asmString) }
?.toSet()
?: emptySet()
val targetKlass = analysisLevel.klass.fullName.replace(Package.SEPARATOR, File.separatorChar)
val targetFiles = listOf(jacocoInstrumentedDir.resolve("$targetKlass.class"))
val additionalFiles = Files.walk(jacocoInstrumentedDir)
.filter { it.isClass }
.filter { additionalValues.any { value -> value.isParent(it.fullyQualifiedName(jacocoInstrumentedDir).asmString) } }
.collect(Collectors.toList())
targetFiles + additionalFiles
}

is MethodLevel -> {
Expand Down Expand Up @@ -258,10 +268,15 @@ open class CoverageReporter(
val returnValue = jcClass.getMethod("run", computerClass, Class::class.java.asArray())
.invoke(jc, computerClass.newInstance(), arrayOf(testClass))

if (logJUnit && !(returnValue as? Result)?.failures.isNullOrEmpty()) {
val resultClass = classLoader.loadClass("org.junit.runner.Result")
val failures = resultClass.getFieldByName("failures")
.also { it.isAccessible = true }
.get(returnValue) as List<*>

if (logJUnit && failures.isNotEmpty()) {
log.debug("Failures:")
(returnValue as? Result)?.failures?.forEach {
log.debug(it.trace)
failures.forEach {
log.debug(it)
}
}
val executionData = ExecutionDataStore()
Expand Down Expand Up @@ -383,17 +398,21 @@ fun reportCoverage(
coverageSaturation.toList()
)
PermanentSaturationCoverageInfo.emit()
coverageSaturation[coverageSaturation.lastKey()]!!
setOf(coverageSaturation[coverageSaturation.lastKey()]!!)
}

else -> coverageReporter.computeCoverage(analysisLevel, testClasses)
}
kexConfig.getPathValue("kex", "coverageJsonLocation")
?.writeText(Json.encodeToString(coverageInfo))

log.info(
coverageInfo.print(kexConfig.getBooleanValue("kex", "printDetailedCoverage", false))
coverageInfo.joinToString(System.lineSeparator()) {
it.print(kexConfig.getBooleanValue("kex", "printDetailedCoverage", false))
}
)

PermanentCoverageInfo.putNewInfo(mode, analysisLevel.toString(), coverageInfo)
PermanentCoverageInfo.putNewInfo(mode, analysisLevel.toString(), coverageInfo.first())
PermanentCoverageInfo.emit()
}
}
Loading

0 comments on commit d34b84f

Please sign in to comment.