Skip to content

Commit

Permalink
TS test framework improvements (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
CaelmBleidd authored Jul 25, 2024
1 parent f4422a3 commit 6680dc4
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 59 deletions.
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
}
}

0 comments on commit 6680dc4

Please sign in to comment.