-
Notifications
You must be signed in to change notification settings - Fork 46
Use symbolic result instead of concrete if it is better #2700
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,6 @@ import org.jacodb.api.ext.jcdbSignature | |
import org.usvm.instrumentation.testcase.api.UTestExecutionExceptionResult | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionFailedResult | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionInitFailedResult | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionResult | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionState | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionSuccessResult | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionTimedOutResult | ||
|
@@ -20,6 +19,10 @@ import org.usvm.instrumentation.util.enclosingClass | |
import org.usvm.instrumentation.util.enclosingMethod | ||
import org.utbot.common.isPublic | ||
import org.utbot.contest.usvm.jc.JcExecution | ||
import org.utbot.contest.usvm.jc.UTestConcreteExecutionResult | ||
import org.utbot.contest.usvm.jc.UTestResultWrapper | ||
import org.utbot.contest.usvm.jc.UTestSymbolicExceptionResult | ||
import org.utbot.contest.usvm.jc.UTestSymbolicSuccessResult | ||
import org.utbot.framework.codegen.domain.builtin.UtilMethodProvider | ||
import org.utbot.framework.plugin.api.ClassId | ||
import org.utbot.framework.plugin.api.Coverage | ||
|
@@ -65,56 +68,91 @@ class JcToUtExecutionConverter( | |
private var uTestProcessResult = instToModelConverter.processUTest() | ||
|
||
fun convert(): UtExecution? { | ||
val coverage = convertCoverage(getTrace(jcExecution.uTestExecutionResult), jcExecution.method.enclosingType.jcClass) | ||
val coverage = convertCoverage(getTrace(jcExecution.uTestExecutionResultWrapper), jcExecution.method.enclosingType.jcClass) | ||
|
||
val utUsvmExecution: UtUsvmExecution = when (val executionResult = jcExecution.uTestExecutionResult) { | ||
is UTestExecutionSuccessResult -> UtUsvmExecution( | ||
stateBefore = convertState(executionResult.initialState, EnvironmentStateKind.INITIAL, jcExecution.method), | ||
stateAfter = convertState(executionResult.resultState, EnvironmentStateKind.FINAL, jcExecution.method), | ||
// TODO usvm-sbft: ask why `UTestExecutionSuccessResult.result` is nullable | ||
result = UtExecutionSuccess(executionResult.result?.let { | ||
jcToUtModelConverter.convert(it, EnvironmentStateKind.FINAL) | ||
} ?: UtVoidModel), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
is UTestExecutionExceptionResult -> { | ||
val utUsvmExecution: UtUsvmExecution = when (jcExecution.uTestExecutionResultWrapper) { | ||
is UTestSymbolicExceptionResult -> { | ||
UtUsvmExecution( | ||
stateBefore = convertState(executionResult.initialState, EnvironmentStateKind.INITIAL, jcExecution.method), | ||
stateAfter = convertState(executionResult.resultState, EnvironmentStateKind.FINAL, jcExecution.method), | ||
stateBefore = constructStateBeforeFromUTest(), | ||
stateAfter = MissingState, | ||
result = createExecutionFailureResult( | ||
executionResult.cause, | ||
jcExecution.method, | ||
exceptionDescriptor = UTestExceptionDescriptor( | ||
type = jcExecution.uTestExecutionResultWrapper.exceptionType, | ||
message = "", | ||
stackTrace = emptyList(), | ||
raisedByUserCode = true, | ||
), | ||
jcTypedMethod = jcExecution.method, | ||
), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
} | ||
|
||
is UTestExecutionInitFailedResult -> { | ||
logger.warn(convertException(executionResult.cause)) { | ||
"Execution failed before method under test call on ${jcExecution.method.method}" | ||
} | ||
null | ||
} | ||
is UTestSymbolicSuccessResult -> { | ||
val resultWrapper = jcExecution.uTestExecutionResultWrapper | ||
resultWrapper.initStatements.forEach { instToModelConverter.processInst(it) } | ||
instToModelConverter.processInst(resultWrapper.result) | ||
|
||
is UTestExecutionFailedResult -> { | ||
logger.error(convertException(executionResult.cause)) { | ||
"Concrete execution failed on ${jcExecution.method.method}" | ||
} | ||
null | ||
} | ||
val resultUtModel = instToModelConverter.findModelByInst(resultWrapper.result) | ||
|
||
is UTestExecutionTimedOutResult -> { | ||
logger.warn { "Timeout on ${jcExecution.method.method}" } | ||
UtUsvmExecution( | ||
stateBefore = constructStateBeforeFromUTest(), | ||
stateAfter = MissingState, | ||
result = UtTimeoutException(TimeoutException("Concrete execution timed out")), | ||
result = UtExecutionSuccess(resultUtModel), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
} | ||
|
||
is UTestConcreteExecutionResult -> | ||
when (val executionResult = jcExecution.uTestExecutionResultWrapper.uTestExecutionResult) { | ||
is UTestExecutionSuccessResult -> UtUsvmExecution( | ||
stateBefore = convertState(executionResult.initialState, EnvironmentStateKind.INITIAL, jcExecution.method), | ||
stateAfter = convertState(executionResult.resultState, EnvironmentStateKind.FINAL, jcExecution.method), | ||
// TODO usvm-sbft: ask why `UTestExecutionSuccessResult.result` is nullable | ||
result = UtExecutionSuccess(executionResult.result?.let { | ||
jcToUtModelConverter.convert(it, EnvironmentStateKind.FINAL) | ||
} ?: UtVoidModel), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
|
||
is UTestExecutionExceptionResult -> { | ||
UtUsvmExecution( | ||
stateBefore = convertState(executionResult.initialState, EnvironmentStateKind.INITIAL, jcExecution.method), | ||
stateAfter = convertState(executionResult.resultState, EnvironmentStateKind.FINAL, jcExecution.method), | ||
result = createExecutionFailureResult(executionResult.cause, jcExecution.method), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
} | ||
|
||
is UTestExecutionInitFailedResult -> { | ||
logger.warn(convertException(executionResult.cause)) { | ||
"Execution failed before method under test call on ${jcExecution.method.method}" | ||
} | ||
null | ||
} | ||
|
||
is UTestExecutionFailedResult -> { | ||
logger.error(convertException(executionResult.cause)) { | ||
"Concrete execution failed on ${jcExecution.method.method}" | ||
} | ||
null | ||
} | ||
|
||
is UTestExecutionTimedOutResult -> { | ||
logger.warn { "Timeout on ${jcExecution.method.method}" } | ||
UtUsvmExecution( | ||
stateBefore = constructStateBeforeFromUTest(), | ||
stateAfter = MissingState, | ||
result = UtTimeoutException(TimeoutException("Concrete execution timed out")), | ||
coverage = coverage, | ||
instrumentation = uTestProcessResult.instrumentation, | ||
) | ||
} | ||
} | ||
} ?: return null | ||
|
||
return utUsvmExecution | ||
|
@@ -206,12 +244,22 @@ class JcToUtExecutionConverter( | |
cache = mutableMapOf() | ||
)) as Throwable | ||
|
||
private fun getTrace(executionResult: UTestExecutionResult): List<JcInst>? = when (executionResult) { | ||
is UTestExecutionExceptionResult -> executionResult.trace | ||
is UTestExecutionInitFailedResult -> executionResult.trace | ||
is UTestExecutionSuccessResult -> executionResult.trace | ||
is UTestExecutionFailedResult -> emptyList() | ||
is UTestExecutionTimedOutResult -> emptyList() | ||
/** | ||
* Gets trace from execution result if it is present. | ||
* | ||
* Otherwise, (e.g. we use symbolic result if concrete fails), | ||
* minimization will take just 'UtSettings.maxUnknownCoverageExecutionsPerMethodPerResultType' executions. | ||
*/ | ||
private fun getTrace(executionResult: UTestResultWrapper): List<JcInst>? = when (executionResult) { | ||
is UTestConcreteExecutionResult -> when (val res = executionResult.uTestExecutionResult) { | ||
is UTestExecutionExceptionResult -> res.trace | ||
is UTestExecutionInitFailedResult -> res.trace | ||
is UTestExecutionSuccessResult -> res.trace | ||
is UTestExecutionFailedResult -> emptyList() | ||
is UTestExecutionTimedOutResult -> emptyList() | ||
} | ||
is UTestSymbolicExceptionResult -> emptyList() | ||
is UTestSymbolicSuccessResult -> emptyList() | ||
Comment on lines
+261
to
+262
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Executions with empty coverage are not minimized. It's somewhat ok for timeout executions, since there can only be so many of them (due to time it takes to register timeout), but symbolic results can be emitted much faster. If it's too difficult to extract any coverage info from the machine, consider merging #2627 into usvm_competitions_2024 with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Merged a copy of that PR into competitions, added a comment here. |
||
} | ||
|
||
private fun convertState( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,31 @@ | ||
package org.utbot.contest.usvm.jc | ||
|
||
import org.jacodb.api.JcType | ||
import org.jacodb.api.JcTypedMethod | ||
import org.usvm.api.JcCoverage | ||
import org.usvm.instrumentation.testcase.UTest | ||
import org.usvm.instrumentation.testcase.api.UTestExecutionResult | ||
import org.usvm.instrumentation.testcase.api.UTestExpression | ||
import org.usvm.instrumentation.testcase.api.UTestInst | ||
|
||
data class JcExecution( | ||
val method: JcTypedMethod, | ||
val uTest: UTest, | ||
val uTestExecutionResult: UTestExecutionResult, | ||
val uTestExecutionResultWrapper: UTestResultWrapper, | ||
val coverage: JcCoverage | ||
) | ||
|
||
sealed interface UTestResultWrapper | ||
|
||
class UTestConcreteExecutionResult( | ||
val uTestExecutionResult: UTestExecutionResult | ||
) : UTestResultWrapper | ||
|
||
class UTestSymbolicExceptionResult( | ||
val exceptionType: JcType | ||
) : UTestResultWrapper | ||
|
||
class UTestSymbolicSuccessResult( | ||
val initStatements: List<UTestInst>, | ||
val result: UTestExpression | ||
) : UTestResultWrapper |
Uh oh!
There was an error while loading. Please reload this page.