Skip to content

Commit 2eefc9e

Browse files
Process some concrete failures gracefully (#2456)
1 parent a5d1af4 commit 2eefc9e

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/UtExecutionResult.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ data class UtConcreteExecutionFailure(override val exception: Throwable) : UtExe
8181

8282
/**
8383
* Represents a failure in instrumented process
84-
* that is not actually caused by concrete execution.
84+
* that is not actually caused by concrete method under test call.
8585
*
86-
* For example, failure may occured during data preparation for a concrete call.
86+
* For example, failure may have occurred during method arguments preparation
87+
* or statics initializers processing during object instance creation.
8788
*/
88-
data class UtConcreteExecutionProcessedFailure(override val exception: Throwable): UtExecutionFailure()
89+
data class UtConcreteExecutionProcessedFailure(override val exception: Throwable) : UtExecutionFailure()
8990

9091
val UtExecutionResult.isSuccess: Boolean
9192
get() = this is UtExecutionSuccess

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,12 @@ import org.utbot.instrumentation.ConcreteExecutor
4848
import org.utbot.instrumentation.instrumentation.Instrumentation
4949
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionData
5050
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionResult
51-
import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrumentation
5251
import org.utbot.taint.*
5352
import org.utbot.taint.model.TaintConfiguration
5453
import soot.jimple.Stmt
5554
import soot.tagkit.ParamNamesTag
5655
import java.lang.reflect.Method
5756
import java.util.function.Consumer
58-
import java.util.function.Predicate
5957
import kotlin.math.min
6058
import kotlin.system.measureTimeMillis
6159

@@ -317,10 +315,7 @@ class UtBotSymbolicEngine(
317315
val concreteExecutionResult =
318316
concreteExecutor.executeConcretely(methodUnderTest, stateBefore, instrumentation, UtSettings.concreteExecutionDefaultTimeoutInInstrumentedProcessMillis)
319317

320-
concreteExecutionResult.processedFailure()?.let { failure ->
321-
emitFailedConcreteExecutionResult(stateBefore, failure.exception)
322-
323-
logger.debug { "Instrumented process failed with exception ${failure.exception} before concrete execution started" }
318+
if (failureCanBeProcessedGracefully(concreteExecutionResult, executionToRollbackOn = null)) {
324319
return@measureTime
325320
}
326321

@@ -668,10 +663,7 @@ class UtBotSymbolicEngine(
668663
UtSettings.concreteExecutionDefaultTimeoutInInstrumentedProcessMillis
669664
)
670665

671-
concreteExecutionResult.processedFailure()?.let { failure ->
672-
emitFailedConcreteExecutionResult(stateBefore, failure.exception)
673-
674-
logger.debug { "Instrumented process failed with exception ${failure.exception} before concrete execution started" }
666+
if (failureCanBeProcessedGracefully(concreteExecutionResult, symbolicUtExecution)) {
675667
return
676668
}
677669

@@ -699,6 +691,29 @@ class UtBotSymbolicEngine(
699691
}
700692
}
701693

694+
private suspend fun FlowCollector<UtResult>.failureCanBeProcessedGracefully(
695+
concreteExecutionResult: UtConcreteExecutionResult,
696+
executionToRollbackOn: UtExecution?,
697+
): Boolean {
698+
concreteExecutionResult.processedFailure()?.let { failure ->
699+
// If concrete execution failed to some reasons that are not process death or cancellation
700+
// when we call something that is processed successfully by symbolic engine,
701+
// we should:
702+
// - roll back to symbolic execution data ignoring failing concrete (is symbolic execution exists);
703+
// - do not emit an execution if there is nothing to roll back on.
704+
705+
// Note that this situation is suspicious anyway, so we log a WARN message about the failure.
706+
executionToRollbackOn?.let {
707+
emit(it)
708+
}
709+
710+
logger.warn { "Instrumented process failed with exception ${failure.exception} before concrete execution started" }
711+
return true
712+
}
713+
714+
return false
715+
}
716+
702717
/**
703718
* Collects entry method statement path for ML. Eliminates duplicated statements, e.g. assignment with invocation
704719
* in right part.

utbot-summary/src/main/kotlin/org/utbot/summary/TagGenerator.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,13 @@ enum class ExecutionGroup {
207207
EXPLICITLY_THROWN_UNCHECKED_EXCEPTIONS,
208208
OVERFLOWS,
209209
TIMEOUTS,
210+
211+
/**
212+
* Executions that caused by `InstrumentedProcessDeath` exception.
213+
* Generated tests will be disabled du to possible JVM crash.
214+
*/
210215
CRASH_SUITE,
216+
211217
TAINT_ANALYSIS,
212218
SECURITY;
213219

@@ -221,10 +227,11 @@ private fun UtExecutionResult.clusterKind() = when (this) {
221227
is UtStreamConsumingFailure -> ExecutionGroup.ERROR_SUITE
222228
is UtOverflowFailure -> ExecutionGroup.OVERFLOWS
223229
is UtTimeoutException -> ExecutionGroup.TIMEOUTS
224-
is UtConcreteExecutionProcessedFailure -> ExecutionGroup.CRASH_SUITE
225230
is UtConcreteExecutionFailure -> ExecutionGroup.CRASH_SUITE
226231
is UtSandboxFailure -> ExecutionGroup.SECURITY
227232
is UtTaintAnalysisFailure -> ExecutionGroup.TAINT_ANALYSIS
233+
is UtConcreteExecutionProcessedFailure ->
234+
error("Processed failure must not be found in generated tests, it can just happen on intermediate phases of tests generation")
228235
}
229236

230237
/**

0 commit comments

Comments
 (0)