Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test framework improvements #199

Merged
merged 1 commit into from
Jul 25, 2024
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
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import org.gradle.plugin.use.PluginDependenciesSpec
object Versions {
const val detekt = "1.18.1"
const val ini4j = "0.5.4"
const val jacodb = "e47c227815"
const val jacodb = "30594f5f7c"
const val juliet = "1.3.2"
const val junit = "5.9.3"
const val kotlin = "1.9.20"
Expand Down
31 changes: 30 additions & 1 deletion usvm-ts/src/main/kotlin/org/usvm/TSTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,33 @@ class TSTest(
val trace: List<EtsStmt>? = null,
)

class TSMethodCoverage
open class TSMethodCoverage

object NoCoverage : TSMethodCoverage()

sealed interface TSObject {
sealed interface TSNumber : TSObject {
data class Integer(val value: Int) : TSNumber

data class Double(val value: kotlin.Double) : TSNumber

val number: kotlin.Double
get() = when (this) {
is Integer -> value.toDouble()
is Double -> value
}
}

data class String(val value: kotlin.String) : TSObject

data class Boolean(val value: kotlin.Boolean) : TSObject


data class Class(val name: String, val properties: Map<String, TSObject>) : TSObject

data object AnyObject : TSObject

data object UndefinedObject : TSObject

data class Array(val values: List<TSObject>) : TSObject
}
22 changes: 22 additions & 0 deletions usvm-ts/src/test/kotlin/org/usvm/samples/Arguments.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.usvm.samples

import org.junit.jupiter.api.Disabled
import org.usvm.TSObject
import org.usvm.util.MethodDescriptor
import org.usvm.util.TSMethodTestRunner
import kotlin.test.Test

class Arguments : TSMethodTestRunner() {
@Test
@Disabled
fun testMinValue() {
discoverProperties<TSObject.TSNumber>(
methodIdentifier = MethodDescriptor(
fileName = "Arguments.ts",
className = "SimpleClass",
methodName = "noArguments",
argumentsNumber = 0
)
)
}
}
8 changes: 4 additions & 4 deletions usvm-ts/src/test/kotlin/org/usvm/samples/MinValue.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package org.usvm.samples

import org.junit.jupiter.api.Disabled
import org.usvm.TSObject
import org.usvm.util.MethodDescriptor
import org.usvm.util.TSMethodTestRunner
import kotlin.test.Test

@Disabled("Not yet implemented")
class MinValue : TSMethodTestRunner() {

@Test
@Disabled
fun testMinValue() {
discoverProperties<Any, Any>(
discoverProperties<TSObject.Array, TSObject.TSNumber>(
methodIdentifier = MethodDescriptor(
fileName = "MinValue",
fileName = "MinValue.ts",
className = globalClassName,
methodName = "findMinValue",
argumentsNumber = 1
Expand Down
92 changes: 39 additions & 53 deletions usvm-ts/src/test/kotlin/org/usvm/util/TSMethodTestRunner.kt
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
package org.usvm.util

import org.jacodb.ets.base.EtsAnyType
import org.jacodb.ets.base.EtsBooleanType
import org.jacodb.ets.base.EtsNumberType
import org.jacodb.ets.base.EtsStringType
import org.jacodb.ets.base.EtsType
import org.jacodb.ets.base.EtsUndefinedType
import org.jacodb.ets.dto.EtsFileDto
import org.jacodb.ets.dto.convertToEtsFile
import org.jacodb.ets.model.EtsFile
import org.jacodb.ets.model.EtsMethod
import org.usvm.NoCoverage
import org.usvm.PathSelectionStrategy
import org.usvm.TSMachine
import org.usvm.TSMethodCoverage
import org.usvm.TSObject
import org.usvm.TSTest
import org.usvm.UMachineOptions
import org.usvm.test.util.TestRunner
import org.usvm.test.util.checkers.ignoreNumberOfAnalysisResults
import kotlin.reflect.KClass
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds

typealias CoverageChecker = (TSMethodCoverage) -> Boolean

open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, TSMethodCoverage>() {

protected val globalClassName = "_DEFAULT_ARK_CLASS"

protected inline fun <reified R> discoverProperties(
protected val doNotCheckCoverage: CoverageChecker = { _ -> true }

protected inline fun <reified R : TSObject> discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (R?) -> Boolean,
invariants: Array<out Function<Boolean>> = emptyArray(),
noinline coverageChecker: CoverageChecker = doNotCheckCoverage,
) {
internalCheck(
target = methodIdentifier,
Expand All @@ -32,14 +45,15 @@ open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, T
extractValuesToCheck = { r -> r.parameters + r.resultValue },
expectedTypesForExtractedValues = arrayOf(typeTransformer(R::class)),
checkMode = CheckMode.MATCH_PROPERTIES,
coverageChecker = { _ -> true }
coverageChecker = coverageChecker
)
}

protected inline fun <reified T, reified R> discoverProperties(
protected inline fun <reified T : TSObject, reified R : TSObject> discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T, R?) -> Boolean,
invariants: Array<out Function<Boolean>> = emptyArray(),
noinline coverageChecker: CoverageChecker = doNotCheckCoverage,
) {
internalCheck(
target = methodIdentifier,
Expand All @@ -49,14 +63,15 @@ open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, T
extractValuesToCheck = { r -> r.parameters + r.resultValue },
expectedTypesForExtractedValues = arrayOf(typeTransformer(T::class), typeTransformer(R::class)),
checkMode = CheckMode.MATCH_PROPERTIES,
coverageChecker = { _ -> true }
coverageChecker = coverageChecker
)
}

protected inline fun <reified T1, reified T2, reified R> discoverProperties(
protected inline fun <reified T1 : TSObject, reified T2 : TSObject, reified R : TSObject> discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T1, T2, R?) -> Boolean,
invariants: Array<out Function<Boolean>> = emptyArray(),
noinline coverageChecker: CoverageChecker = doNotCheckCoverage,
) {
internalCheck(
target = methodIdentifier,
Expand All @@ -70,57 +85,27 @@ open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, T
typeTransformer(R::class)
),
checkMode = CheckMode.MATCH_PROPERTIES,
coverageChecker = { _ -> true }
)
}

protected inline fun <reified T1, reified T2, reified T3, reified R> discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T1, T2, T3, R?) -> Boolean,
invariants: Array<out Function<Boolean>> = emptyArray(),
) {
internalCheck(
target = methodIdentifier,
analysisResultsNumberMatcher = ignoreNumberOfAnalysisResults,
analysisResultsMatchers = analysisResultMatchers,
invariants = invariants,
extractValuesToCheck = { r -> r.parameters + r.resultValue },
expectedTypesForExtractedValues = arrayOf(
typeTransformer(T1::class),
typeTransformer(T2::class),
typeTransformer(T3::class),
typeTransformer(R::class)
),
checkMode = CheckMode.MATCH_PROPERTIES,
coverageChecker = { _ -> true }
)
}

protected inline fun <reified T1, reified T2, reified T3, reified T4, reified R> discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T1, T2, T3, T4, R?) -> Boolean,
invariants: Array<out Function<Boolean>> = emptyArray(),
) {
internalCheck(
target = methodIdentifier,
analysisResultsNumberMatcher = ignoreNumberOfAnalysisResults,
analysisResultsMatchers = analysisResultMatchers,
invariants = invariants,
extractValuesToCheck = { r -> r.parameters + r.resultValue },
expectedTypesForExtractedValues = arrayOf(
typeTransformer(T1::class),
typeTransformer(T2::class),
typeTransformer(T3::class),
typeTransformer(T4::class),
typeTransformer(R::class)
),
checkMode = CheckMode.MATCH_PROPERTIES,
coverageChecker = { _ -> true }
coverageChecker = coverageChecker
)
}

override val typeTransformer: (Any?) -> EtsType
get() = TODO("Not yet implemented")
get() = {
require(it is KClass<*>) { "Only TSObjects are allowed" }

when (it) {
TSObject.AnyObject::class -> EtsAnyType
TSObject.Array::class -> TODO()
TSObject.Boolean::class -> EtsBooleanType
TSObject.Class::class -> TODO()
TSObject.String::class -> EtsStringType
TSObject.TSNumber::class -> EtsNumberType
TSObject.TSNumber.Double::class -> EtsNumberType
TSObject.TSNumber.Integer::class -> EtsNumberType
TSObject.UndefinedObject::class -> EtsUndefinedType
else -> error("Should not be called")
}
}

override val checkType: (EtsType?, EtsType?) -> Boolean
get() = TODO("Not yet implemented")
Expand Down Expand Up @@ -157,7 +142,7 @@ open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, T
}
}

override val coverageRunner: (List<TSTest>) -> TSMethodCoverage = TODO()
override val coverageRunner: (List<TSTest>) -> TSMethodCoverage = { _ -> NoCoverage }

override var options: UMachineOptions = UMachineOptions(
pathSelectionStrategies = listOf(PathSelectionStrategy.CLOSEST_TO_UNCOVERED_RANDOM),
Expand All @@ -169,6 +154,7 @@ open class TSMethodTestRunner : TestRunner<TSTest, MethodDescriptor, EtsType?, T
)
}


data class MethodDescriptor(
val fileName: String,
val className: String,
Expand Down
13 changes: 13 additions & 0 deletions usvm-ts/src/test/resources/samples/Arguments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class SimpleClass {
noArguments(): Number {
return 42
}

singleArgument(a) {
return a
}

thisArgument(): SimpleClass {
return this
}
}
Loading