Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ object Libs {
version = Versions.onnxruntime
)

val onnxruntime_gpu = dep(
group = "com.microsoft.onnxruntime",
name = "onnxruntime_gpu",
version = Versions.onnxruntime
)

val ktor_server_core = dep(
group = "io.ktor",
name = "ktor-server-core",
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ findProject(":usvm-python:usvm-python-runner")?.name = "usvm-python-runner"
include("usvm-python:usvm-python-commons")
findProject(":usvm-python:usvm-python-commons")?.name = "usvm-python-commons"
include("usvm-ml-gameserver")
include("usvm-runner")

pluginManagement {
resolutionStrategy {
Expand Down
1 change: 1 addition & 0 deletions usvm-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
testImplementation(Libs.ksmt_yices)

implementation(Libs.onnxruntime)
implementation(Libs.onnxruntime_gpu)
}

publishing {
Expand Down
19 changes: 16 additions & 3 deletions usvm-core/src/main/kotlin/org/usvm/utils/OnnxModelImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,31 @@ import ai.onnxruntime.OnnxTensor
import ai.onnxruntime.OrtEnvironment
import ai.onnxruntime.OrtSession
import org.usvm.StateId
import org.usvm.logger
import org.usvm.statistics.BasicBlock
import org.usvm.statistics.BlockGraph
import org.usvm.util.OnnxModel
import java.nio.FloatBuffer
import java.nio.LongBuffer
import java.nio.file.Path

enum class Mode {
CPU,
GPU
}

class OnnxModelImpl<Block: BasicBlock>(
pathToONNX: Path
pathToONNX: String,
mode: Mode
): OnnxModel<Game<Block>> {
private val env: OrtEnvironment = OrtEnvironment.getEnvironment()
private val session: OrtSession = env.createSession(pathToONNX.toString())
private val sessionOptions: OrtSession.SessionOptions = OrtSession.SessionOptions().apply {
if (mode == Mode.GPU) {
addCUDA()
} else {
logger.info("Using CPU execution provider.")
}
}
private val session: OrtSession = env.createSession(pathToONNX, sessionOptions)

override fun predictState(game: Game<Block>): UInt {
val stateIds = mutableMapOf<StateId, Int>()
Expand Down
2 changes: 1 addition & 1 deletion usvm-ml-gameserver/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tasks.test {
dependencies {
implementation(project(":usvm-jvm"))
implementation(project(":usvm-core"))
implementation(project(":usvm-runner"))
implementation(Libs.jacodb_api_jvm)
implementation(Libs.jacodb_core)

Expand All @@ -44,6 +45,5 @@ dependencies {
implementation(Libs.kotlinx_cli)
implementation(Libs.slf4j_simple)

implementation("io.github.rchowell:dotlin:1.0.2")
testImplementation(kotlin("test"))
}
57 changes: 0 additions & 57 deletions usvm-ml-gameserver/src/main/kotlin/org.usvm/JavaMethodRunner.kt

This file was deleted.

2 changes: 1 addition & 1 deletion usvm-ml-gameserver/src/main/kotlin/org.usvm/OracleImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.usvm.gameserver.GameState
import org.usvm.statistics.BasicBlock
import org.usvm.util.Oracle
import org.usvm.utils.Game
import org.usvm.util.createGameState
import org.usvm.gameserver.serialization.createGameState

class OracleImpl<Block: BasicBlock>(
val predict: (GameState) -> UInt
Expand Down
31 changes: 19 additions & 12 deletions usvm-ml-gameserver/src/main/kotlin/org.usvm/gameserver/Explorer.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
@file:Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")

package org.usvm.gameserver

import org.usvm.JavaMethodRunner
import org.usvm.runner.JavaMethodRunner
import org.usvm.OracleImpl
import org.usvm.PathSelectionStrategy
import org.usvm.UMachineOptions
import org.usvm.runner.defaultOptions
import org.usvm.statistics.BasicBlock
import kotlin.math.floor

Expand All @@ -22,10 +23,10 @@ fun randomExplorer(
step.gameStep.stateId
}

val (className, methodName) = extractClassAndMethod(gameMap.nameOfObjectToCover)
val runner = JavaMethodRunner(gameMap, OracleImpl<BasicBlock>(predict))
val options = cloneDefaultOptions(gameMap, predict)
val runner = JavaMethodRunner(options, gameMap.assemblyFullName)

val (results, percentageCoverage) = runner.cover(className, methodName)
val (results, percentageCoverage) = runner.cover(gameMap.nameOfObjectToCover)
val errors = results.count { it.isExceptional }
val tests = results.size - errors

Expand All @@ -36,10 +37,16 @@ fun randomExplorer(
)
}

private fun extractClassAndMethod(fullName: String): Pair<String, String> {
val parts = fullName.split('.')
val className = parts.dropLast(1).joinToString(".")
val methodName = parts.last()

return Pair(className, methodName)
private fun cloneDefaultOptions(gameMap: GameMap, predict: (GameState) -> UInt): UMachineOptions {
val defaultSearcher = when (gameMap.defaultSearcher) {
Searcher.BFS -> PathSelectionStrategy.BFS
Searcher.DFS -> PathSelectionStrategy.DFS
}
val stepLimit = (gameMap.stepsToStart + gameMap.stepsToStart).toULong()
return defaultOptions.copy(
pathSelectionStrategies = listOf(defaultSearcher, PathSelectionStrategy.AI),
stepLimit = stepLimit,
stepsToStart = gameMap.stepsToStart,
oracle = OracleImpl<BasicBlock>(predict)
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.usvm.util
package org.usvm.gameserver.serialization

import org.usvm.gameserver.GameEdgeLabel
import org.usvm.gameserver.GameMapEdge
Expand Down
32 changes: 32 additions & 0 deletions usvm-runner/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("usvm.kotlin-conventions")
kotlin
}

repositories {
mavenCentral()
}

tasks.test {
useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
kotlinOptions.allWarningsAsErrors = false
}

dependencies {
implementation(project(":usvm-jvm"))
implementation(project(":usvm-core"))
implementation(Libs.jacodb_api_jvm)
implementation(Libs.jacodb_core)
implementation(Libs.kotlinx_cli)

implementation(Libs.slf4j_simple)
implementation(Libs.logback)

implementation("io.github.rchowell:dotlin:1.0.2")
testImplementation(kotlin("test"))
}
57 changes: 57 additions & 0 deletions usvm-runner/src/main/kotlin/org/usvm/runner/JavaMethodRunner.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.usvm.runner

import org.usvm.CoverageZone
import org.usvm.PathSelectionStrategy
import org.usvm.PathSelectorCombinationStrategy
import org.usvm.UMachineOptions
import org.usvm.machine.JcMachine
import org.usvm.machine.state.JcState
import org.usvm.runner.util.JacoDBContainer
import org.usvm.runner.util.getJcMethodByName
import org.usvm.runner.util.loadClasspathFromJar
import org.usvm.runner.util.mapsKey
import kotlin.time.Duration

class JavaMethodRunner(val options: UMachineOptions, classpath: String) {
val jacodbCpKey: String
get() = mapsKey

val cp by lazy {
val classpath = loadClasspathFromJar(classpath)
JacoDBContainer(jacodbCpKey, classpath).cp
}

fun cover(methodFullName: String): Pair<List<JcState>, Float> {
val (className, methodName) = extractClassAndMethod(methodFullName)
return cover(className, methodName)
}

fun cover(className: String, methodName: String): Pair<List<JcState>, Float> {
val jcMethod = cp.getJcMethodByName(className, methodName)

val (states, percentageCoverage) = JcMachine(cp, options, interpreterObserver = null).use { machine ->
machine.analyze(jcMethod.method, targets = emptyList())
}
return states to percentageCoverage
}

private fun extractClassAndMethod(fullName: String): Pair<String, String> {
val parts = fullName.split('.')
val className = parts.dropLast(1).joinToString(".")
val methodName = parts.last()

return Pair(className, methodName)
}
}

val defaultOptions = UMachineOptions(
pathSelectionStrategies = listOf(PathSelectionStrategy.AI),
pathSelectorCombinationStrategy = PathSelectorCombinationStrategy.SEQUENTIAL,
coverageZone = CoverageZone.METHOD,
exceptionsPropagation = true,
solverTimeout = Duration.INFINITE,
timeout = Duration.INFINITE,
typeOperationsTimeout = Duration.INFINITE,
useSolverForForks = false,
stepLimit = 2000U
)
63 changes: 63 additions & 0 deletions usvm-runner/src/main/kotlin/org/usvm/runner/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.usvm.runner

import ch.qos.logback.classic.Level
import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.default
import kotlinx.cli.required
import org.slf4j.LoggerFactory
import org.usvm.statistics.BasicBlock
import org.usvm.utils.Mode
import org.usvm.utils.OnnxModelImpl


fun main(args: Array<String>) {
val parser = ArgParser("usvm.Runner")
val model by parser.option(
ArgType.String,
fullName = "model",
shortName = "m",
description = "Path to ONNX model."
).required()

val path by parser.option(
ArgType.String,
fullName = "classpath",
shortName = "cp",
description = "Path to Java classpath."
).required()

val mode by parser.option(
ArgType.Choice<Mode>(),
fullName = "mode",
description = "Mode to run inference in. Could be either CPU or GPU, the default is former."
).default(Mode.CPU)

val methodFullName by parser.option(
ArgType.String,
fullName = "method",
description = "Full name of method to cover including package and class name."
).required()

parser.parse(args)


val runner = JavaMethodRunner(
defaultOptions.copy(oracle = OnnxModelImpl<BasicBlock>(model, mode)),
classpath = path
)

// setLogLevel("ROOT", Level.DEBUG)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?



runner.cover(methodFullName)
}

// evil logger hack

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

@Suppress("unused")
private fun setLogLevel(loggerName: String, level: Level) {
val loggerContext = LoggerFactory.getILoggerFactory() as ch.qos.logback.classic.LoggerContext
val logger = loggerContext.getLogger(loggerName)
logger.level = level
}

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.usvm.runner.util

import io.github.rchowell.dotlin.DotNodeShape
import io.github.rchowell.dotlin.digraph
import org.usvm.statistics.BasicBlock
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.usvm.util
package org.usvm.runner.util

import kotlinx.coroutines.runBlocking
import org.jacodb.api.jvm.JcClasspath
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.usvm.util
package org.usvm.runner.util

import org.jacodb.api.jvm.JcClasspath
import org.jacodb.api.jvm.JcTypedMethod
Expand Down
11 changes: 11 additions & 0 deletions usvm-runner/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<logger name="io.netty" level="INFO"/>
</configuration>
Loading