@@ -13,6 +13,7 @@ import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrument
1313
1414class RerunningConcreteExecutionContext (
1515 private val delegateContext : ConcreteExecutionContext ,
16+ private val maxRerunsPerMethod : Int ,
1617 private val rerunTimeoutInMillis : Long = 10L * UtSettings .concreteExecutionDefaultTimeoutInInstrumentedProcessMillis,
1718) : ConcreteExecutionContext by delegateContext {
1819 companion object {
@@ -23,31 +24,40 @@ class RerunningConcreteExecutionContext(
2324 executions : List <UtExecution >,
2425 methodUnderTest : ExecutableId ,
2526 rerunExecutor : ConcreteExecutor <UtConcreteExecutionResult , UtExecutionInstrumentation >,
26- ): List <UtExecution > = delegateContext.transformExecutionsAfterMinimization(
27- executions,
28- methodUnderTest,
29- rerunExecutor
30- ).map { execution ->
31- runBlocking {
32- val result = try {
33- rerunExecutor.executeConcretely(
34- methodUnderTest = methodUnderTest,
35- stateBefore = execution.stateBefore,
36- instrumentation = emptyList(),
37- timeoutInMillis = rerunTimeoutInMillis,
38- isRerun = true ,
39- )
40- } catch (e: Throwable ) {
41- // we can't update execution result if we don't have a result
42- logger.warn(e) { " Rerun failed, keeping original result for execution [$execution ]" }
43- return @runBlocking execution
44- }
45- execution.copy(
46- stateBefore = result.stateBefore,
47- stateAfter = result.stateAfter,
48- result = result.result,
49- coverage = result.coverage,
50- )
51- }
27+ ): List <UtExecution > {
28+ @Suppress(" NAME_SHADOWING" )
29+ val executions = delegateContext.transformExecutionsAfterMinimization(
30+ executions,
31+ methodUnderTest,
32+ rerunExecutor
33+ )
34+ // it's better to rerun executions with non-empty coverage,
35+ // because executions with empty coverage are often duplicated
36+ .sortedBy { it.coverage?.coveredInstructions.isNullOrEmpty() }
37+ return executions
38+ .take(maxRerunsPerMethod)
39+ .map { execution ->
40+ runBlocking {
41+ val result = try {
42+ rerunExecutor.executeConcretely(
43+ methodUnderTest = methodUnderTest,
44+ stateBefore = execution.stateBefore,
45+ instrumentation = emptyList(),
46+ timeoutInMillis = rerunTimeoutInMillis,
47+ isRerun = true ,
48+ )
49+ } catch (e: Throwable ) {
50+ // we can't update execution result if we don't have a result
51+ logger.warn(e) { " Rerun failed, keeping original result for execution [$execution ]" }
52+ return @runBlocking execution
53+ }
54+ execution.copy(
55+ stateBefore = result.stateBefore,
56+ stateAfter = result.stateAfter,
57+ result = result.result,
58+ coverage = result.coverage,
59+ )
60+ }
61+ } + executions.drop(maxRerunsPerMethod)
5262 }
5363}
0 commit comments