Skip to content

Commit

Permalink
Engine process UnitTestBot#2 (UnitTestBot#1067)
Browse files Browse the repository at this point in the history
[utbot-rd]
1. engine out-of-process
2. removed jdk8+ api calls in engine-related code
3. removed reflection in utbot-intellij to support idea 2022
4. bumped idea version and plugin sdk
5. reactive settings
6. ClientProcessBuilder to support out-of-process
7. moved sarifs, test generation, code generation and TestGenerationReport to another process
  • Loading branch information
Domonion authored and AbdullinAM committed Oct 17, 2022
1 parent dba55a5 commit 720964d
Show file tree
Hide file tree
Showing 62 changed files with 3,851 additions and 1,009 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ allprojects {
override fun beforeSuite(suite: TestDescriptor) {}
override fun beforeTest(testDescriptor: TestDescriptor) {}
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {
println("[$testDescriptor.classDisplayName] [$testDescriptor.displayName]: $result.resultType")
println("[$testDescriptor.classDisplayName] [$testDescriptor.displayName]: $result.resultType, length - ${(result.endTime - result.startTime) / 1000.0} sec")
}

override fun afterSuite(testDescriptor: TestDescriptor, result: TestResult) {
Expand Down
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ kotlin.code.style=official
# IU, IC, PC, PY, WS...
ideType=IC

pythonCommunityPluginVersion=212.5457.59
pythonCommunityPluginVersion=222.4167.37
#Version numbers: https://plugins.jetbrains.com/plugin/631-python/versions
pythonUltimatePluginVersion=212.5457.59
pythonUltimatePluginVersion=222.4167.37

junit5Version=5.8.0-RC1
junit4Version=4.13.2
Expand All @@ -14,7 +14,7 @@ mockitoVersion=3.5.13
z3Version=4.8.9.1
z3JavaApiVersion=4.8.9
sootCommitHash=1f34746
kotlinVersion=1.7.10
kotlinVersion=1.7.20
log4j2Version=2.13.3
coroutinesVersion=1.6.3
collectionsVersion=0.3.4
Expand Down
85 changes: 69 additions & 16 deletions utbot-core/src/main/kotlin/org/utbot/common/AbstractSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,33 @@ import java.util.*
import mu.KLogger
import org.utbot.common.PathUtil.toPath
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

abstract class AbstractSettings(
interface SettingsContainer {
fun <T> settingFor(defaultValue: T, converter: (String) -> T): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>>
}

interface SettingsContainerFactory {
fun createSettingsContainer(
logger: KLogger,
defaultKeyForSettingsPath: String,
defaultSettingsPath: String? = null) : SettingsContainer
}

class PropertiesSettingsContainer(
private val logger: KLogger,
defaultKeyForSettingsPath: String,
defaultSettingsPath: String? = null
) {
protected val properties = Properties().also { props ->
defaultSettingsPath: String? = null): SettingsContainer {
companion object: SettingsContainerFactory {
override fun createSettingsContainer(
logger: KLogger,
defaultKeyForSettingsPath: String,
defaultSettingsPath: String?
): SettingsContainer = PropertiesSettingsContainer(logger, defaultKeyForSettingsPath, defaultSettingsPath)
}

private val properties = Properties().also { props ->
val settingsPath = System.getProperty(defaultKeyForSettingsPath) ?: defaultSettingsPath
val settingsPathFile = settingsPath?.toPath()?.toFile()
if (settingsPathFile?.exists() == true) {
Expand All @@ -27,18 +46,18 @@ abstract class AbstractSettings(
}
}

protected val settingsValues: MutableMap<KProperty<*>, Any?> = mutableMapOf()
private val settingsValues: MutableMap<KProperty<*>, Any?> = mutableMapOf()

inner class SettingDelegate<T>(val property: KProperty<*>, val initializer: () -> T) {
inner class SettingDelegate<T>(val property: KProperty<*>, val initializer: () -> T): ReadWriteProperty<Any?, T> {
private var value = initializer()

init {
updateSettingValue()
}

operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
override operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
updateSettingValue()
}
Expand All @@ -48,10 +67,10 @@ abstract class AbstractSettings(
}
}

protected fun <T> getProperty(
override fun <T> settingFor(
defaultValue: T,
converter: (String) -> T
): PropertyDelegateProvider<Any?, SettingDelegate<T>> {
): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>> {
return PropertyDelegateProvider { _, property ->
SettingDelegate(property) {
try {
Expand All @@ -64,17 +83,51 @@ abstract class AbstractSettings(
}
}

override fun toString(): String =
settingsValues
.mapKeys { it.key.name }
.entries
.sortedBy { it.key }
.joinToString(separator = System.lineSeparator()) { "\t${it.key}=${it.value}" }
}

abstract class AbstractSettings(
logger: KLogger,
defaultKeyForSettingsPath: String,
defaultSettingsPath: String? = null) {
private val container: SettingsContainer = createSettingsContainer(logger, defaultKeyForSettingsPath, defaultSettingsPath)
init {
allSettings[defaultKeyForSettingsPath] = this
}
companion object : SettingsContainerFactory {
val allSettings = mutableMapOf<String, AbstractSettings>()
private var factory: SettingsContainerFactory? = null
override fun createSettingsContainer(
logger: KLogger,
defaultKeyForSettingsPath: String,
defaultSettingsPath: String?
): SettingsContainer {
return (factory ?: PropertiesSettingsContainer).createSettingsContainer(logger, defaultKeyForSettingsPath, defaultSettingsPath)
}

fun setupFactory(factory: SettingsContainerFactory) {
this.factory = factory
}
}

protected fun <T> getProperty(
defaultValue: T,
converter: (String) -> T
): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>> {
return container.settingFor(defaultValue, converter)
}

protected fun getBooleanProperty(defaultValue: Boolean) = getProperty(defaultValue, String::toBoolean)
protected fun getIntProperty(defaultValue: Int) = getProperty(defaultValue, String::toInt)
protected fun getLongProperty(defaultValue: Long) = getProperty(defaultValue, String::toLong)
protected fun getStringProperty(defaultValue: String) = getProperty(defaultValue) { it }
protected inline fun <reified T : Enum<T>> getEnumProperty(defaultValue: T) =
getProperty(defaultValue) { enumValueOf(it) }

override fun toString(): String =
settingsValues
.mapKeys { it.key.name }
.entries
.sortedBy { it.key }
.joinToString(separator = System.lineSeparator()) { "\t${it.key}=${it.value}" }
override fun toString(): String = container.toString()
}
2 changes: 1 addition & 1 deletion utbot-core/src/main/kotlin/org/utbot/common/KClassUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import kotlin.reflect.KClass

val Class<*>.packageName: String get() = `package`?.name?:""
val Class<*>.nameOfPackage: String get() = `package`?.name?:""

fun Method.invokeCatching(obj: Any?, args: List<Any?>) = try {
Result.success(invoke(obj, *args.toTypedArray()))
Expand Down
2 changes: 2 additions & 0 deletions utbot-core/src/main/kotlin/org/utbot/common/Logging.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.utbot.common

import mu.KLogger
import java.time.format.DateTimeFormatter

val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS")

class LoggerWithLogMethod(val logger: KLogger, val logMethod: (() -> Any?) -> Unit)

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

import mu.KotlinLogging
import org.utbot.common.AbstractSettings
import org.utbot.common.PropertiesSettingsContainer
import kotlin.reflect.KProperty

private val logger = KotlinLogging.logger {}
Expand All @@ -17,30 +18,6 @@ internal val utbotHomePath = "${System.getProperty("user.home")}/.utbot"
private val defaultSettingsPath = "$utbotHomePath/settings.properties"
private const val defaultKeyForSettingsPath = "utbot.settings.path"

/**
* Stores current values for each setting from [UtSettings].
*/
private val settingsValues: MutableMap<KProperty<*>, Any?> = mutableMapOf()

internal class SettingDelegate<T>(val property: KProperty<*>, val initializer: () -> T) {
private var value = initializer()

init {
updateSettingValue()
}

operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
updateSettingValue()
}

private fun updateSettingValue() {
settingsValues[property] = value
}
}

/**
* Default concrete execution timeout (in milliseconds).
*/
Expand Down Expand Up @@ -282,7 +259,7 @@ object UtSettings : AbstractSettings(
)

/**
* Determines whether should errors from a child process be written to a log file or suppressed.
* Determines whether should errors from a child process and idea engine process be written to a log file or suppressed.
* Note: being enabled, this option can highly increase disk usage when using ContestEstimator.
*
* False by default (for saving disk space).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,7 @@ import org.utbot.framework.plugin.api.util.shortClassId
import org.utbot.framework.plugin.api.util.supertypeOfAnonymousClass
import org.utbot.framework.plugin.api.util.toReferenceTypeBytecodeSignature
import org.utbot.framework.plugin.api.util.voidClassId
import soot.ArrayType
import soot.BooleanType
import soot.ByteType
import soot.CharType
import soot.DoubleType
import soot.FloatType
import soot.IntType
import soot.LongType
import soot.RefType
import soot.ShortType
import soot.SootClass
import soot.Type
import soot.VoidType
import soot.*
import soot.jimple.JimpleBody
import soot.jimple.Stmt
import java.io.File
Expand All @@ -58,6 +46,7 @@ const val SYMBOLIC_NULL_ADDR: Int = 0
data class UtMethodTestSet(
val method: ExecutableId,
val executions: List<UtExecution> = emptyList(),
// in idea process this property is null
val jimpleBody: JimpleBody? = null,
val errors: Map<String, Int> = emptyMap(),
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.utbot.common.nameOfPackage
import org.utbot.framework.plugin.services.JdkInfoDefaultProvider
import org.utbot.framework.util.SootUtils

Expand Down
4 changes: 4 additions & 0 deletions utbot-framework/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ dependencies {
api project(':utbot-instrumentation')
api project(':utbot-summary')
api project(':utbot-framework-api')
api project(':utbot-rd')

implementation group: 'com.jetbrains.rd', name: 'rd-framework', version: '2022.3.1'
implementation group: 'com.jetbrains.rd', name: 'rd-core', version: '2022.3.1'

implementation "com.github.UnitTestBot:soot:${sootCommitHash}"
implementation group: 'com.esotericsoftware.kryo', name: 'kryo5', version: kryoVersion
// this is necessary for serialization of some collections
implementation group: 'de.javakaffee', name: 'kryo-serializers', version: kryoSerializersVersion

implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: jacksonVersion
implementation group: 'org.sosy-lab', name: 'javasmt-solver-z3', version: javasmtSolverZ3Version
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.utbot.analytics

import mu.KotlinLogging
import org.utbot.framework.PathSelectorType
import org.utbot.framework.UtSettings

private val logger = KotlinLogging.logger {}

object AnalyticsConfigureUtil {
/**
* Configures utbot-analytics models for the better path selection.
*
* NOTE: If analytics configuration for the NN Path Selector could not be loaded,
* it switches to the [PathSelectorType.INHERITORS_SELECTOR].
*/
fun configureML() {
logger.info { "PathSelectorType: ${UtSettings.pathSelectorType}" }

if (UtSettings.pathSelectorType == PathSelectorType.ML_SELECTOR) {
val analyticsConfigurationClassPath = UtSettings.analyticsConfigurationClassPath
tryToSetUpMLSelector(analyticsConfigurationClassPath)
}

if (UtSettings.pathSelectorType == PathSelectorType.TORCH_SELECTOR) {
val analyticsConfigurationClassPath = UtSettings.analyticsTorchConfigurationClassPath
tryToSetUpMLSelector(analyticsConfigurationClassPath)
}
}

private fun tryToSetUpMLSelector(analyticsConfigurationClassPath: String) {
try {
Class.forName(analyticsConfigurationClassPath)
Predictors.stateRewardPredictor = EngineAnalyticsContext.mlPredictorFactory()

logger.info { "RewardModelPath: ${UtSettings.modelPath}" }
} catch (e: ClassNotFoundException) {
logger.error {
"Configuration of the predictors from the utbot-analytics module described in the class: " +
"$analyticsConfigurationClassPath is not found!"
}

logger.info(e) {
"Error while initialization of ${UtSettings.pathSelectorType}. Changing pathSelectorType on INHERITORS_SELECTOR"
}
UtSettings.pathSelectorType = PathSelectorType.INHERITORS_SELECTOR
}
catch (e: Exception) { // engine not found, for example
logger.error { e.message }
UtSettings.pathSelectorType = PathSelectorType.INHERITORS_SELECTOR
}
}

}
4 changes: 2 additions & 2 deletions utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.utbot.engine

import org.utbot.api.mock.UtMock
import org.utbot.common.packageName
import org.utbot.engine.overrides.UtArrayMock
import org.utbot.engine.overrides.UtLogicMock
import org.utbot.engine.overrides.UtOverrideMock
Expand All @@ -18,6 +17,7 @@ import java.util.concurrent.atomic.AtomicInteger
import kotlin.reflect.KFunction2
import kotlin.reflect.KFunction5
import kotlinx.collections.immutable.persistentListOf
import org.utbot.common.nameOfPackage
import org.utbot.engine.util.mockListeners.MockListenerController
import org.utbot.framework.util.isInaccessibleViaReflection
import soot.BooleanType
Expand Down Expand Up @@ -361,7 +361,7 @@ val assumeOrExecuteConcretelyBytecodeSignature: String
val disableClassCastExceptionCheckBytecodeSignature: String
get() = disableClassCastExceptionCheckMethod.executableId.signature

internal val UTBOT_OVERRIDE_PACKAGE_NAME = UtOverrideMock::class.java.packageName
internal val UTBOT_OVERRIDE_PACKAGE_NAME = UtOverrideMock::class.java.nameOfPackage

private val arraycopyMethod : KFunction5<Array<out Any>, Int, Array<out Any>, Int, Int, Unit> = UtArrayMock::arraycopy
internal val utArrayMockArraycopyMethodName = arraycopyMethod.name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.utbot.external.api

import org.utbot.common.FileUtil
import org.utbot.common.nameOfPackage
import org.utbot.framework.UtSettings
import org.utbot.framework.codegen.ForceStaticMocking
import org.utbot.framework.codegen.Junit5
Expand Down Expand Up @@ -57,7 +58,7 @@ object UtBotJavaApi {
staticsMocking: StaticsMocking = NoStaticMocking,
generateWarningsForStaticMocking: Boolean = false,
forceStaticMocking: ForceStaticMocking = ForceStaticMocking.DO_NOT_FORCE,
testClassPackageName: String = classUnderTest.packageName
testClassPackageName: String = classUnderTest.nameOfPackage
): String {

val utContext = UtContext(classUnderTest.classLoader)
Expand Down
Loading

0 comments on commit 720964d

Please sign in to comment.