@@ -13,6 +13,7 @@ import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrument
13
13
14
14
class RerunningConcreteExecutionContext (
15
15
private val delegateContext : ConcreteExecutionContext ,
16
+ private val maxRerunsPerMethod : Int ,
16
17
private val rerunTimeoutInMillis : Long = 10L * UtSettings .concreteExecutionDefaultTimeoutInInstrumentedProcessMillis,
17
18
) : ConcreteExecutionContext by delegateContext {
18
19
companion object {
@@ -23,31 +24,40 @@ class RerunningConcreteExecutionContext(
23
24
executions : List <UtExecution >,
24
25
methodUnderTest : ExecutableId ,
25
26
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)
52
62
}
53
63
}
0 commit comments