11package org.utbot.engine
22
3- import kotlinx.coroutines.flow.Flow
4- import kotlinx.coroutines.flow.flow
53import kotlinx.coroutines.runBlocking
64import mu.KotlinLogging
75import org.jacodb.approximation.Approximations
@@ -24,10 +22,10 @@ import org.utbot.framework.fuzzer.ReferencePreservingIntIdGenerator
2422import org.utbot.framework.plugin.api.ExecutableId
2523import org.utbot.framework.plugin.api.InstrumentedProcessDeathException
2624import org.utbot.framework.plugin.api.UtConcreteExecutionFailure
25+ import org.utbot.framework.plugin.api.UtConcreteExecutionProcessedFailure
2726import org.utbot.framework.plugin.api.UtError
2827import org.utbot.framework.plugin.api.UtFailedExecution
2928import org.utbot.framework.plugin.api.UtResult
30- import org.utbot.framework.plugin.api.UtSymbolicExecution
3129import org.utbot.framework.plugin.api.util.utContext
3230import org.utbot.framework.plugin.services.JdkInfoService
3331import org.utbot.instrumentation.ConcreteExecutor
@@ -36,6 +34,7 @@ import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrument
3634import org.utbot.usvm.converter.JcToUtExecutionConverter
3735import org.utbot.usvm.converter.SimpleInstructionIdProvider
3836import org.utbot.usvm.converter.UtExecutionInitialState
37+ import org.utbot.usvm.converter.UtUsvmExecution
3938import org.utbot.usvm.converter.toExecutableId
4039import org.utbot.usvm.jc.JcContainer
4140import org.utbot.usvm.jc.JcExecution
@@ -56,73 +55,75 @@ object UsvmSymbolicEngine {
5655 classpath : String ,
5756 concreteExecutionContext : ConcreteExecutionContext ,
5857 timeoutMillis : Long
59- ): Flow <Pair <ExecutableId , UtResult >> = flow {
60- var analysisResult: AnalysisResult ? = null
58+ ): List <Pair <ExecutableId , UtResult >> {
6159
60+ val collectedExecutions = mutableListOf<Pair <ExecutableId , UtResult >>()
6261 val classpathFiles = classpath.split(File .pathSeparator).map { File (it) }
63- val jcContainer = createJcContainer(classpathFiles)
6462
65- val jcMethods = methods
66- .mapNotNull { methodId -> jcContainer.cp.findMethodOrNull(methodId).also {
67- if (it == null ) {
68- logger.error { " Method [$methodId ] not found in jcClasspath [${jcContainer.cp} ]" }
63+ createJcContainer(classpathFiles).use { jcContainer ->
64+ val jcMethods = methods
65+ .mapNotNull { methodId ->
66+ jcContainer.cp.findMethodOrNull(methodId).also {
67+ if (it == null ) {
68+ logger.error { " Method [$methodId ] not found in jcClasspath [${jcContainer.cp} ]" }
69+ }
70+ }
6971 }
70- }
71- }
7272
73- JcMachine (
74- cp = jcContainer.cp,
75- options = UMachineOptions (
76- timeout = timeoutMillis.milliseconds,
77- pathSelectionStrategies = listOf (PathSelectionStrategy .CLOSEST_TO_UNCOVERED_RANDOM ),
78- pathSelectorFairnessStrategy = PathSelectorFairnessStrategy .COMPLETELY_FAIR ,
79- solverType = SolverType .Z3 ,
80- )
81- ).use { jcMachine ->
82- jcMachine.analyzeAsync(
83- forceTerminationTimeout = (timeoutMillis * 1.1 + 2000 ).toLong(),
84- methods = jcMethods,
85- targets = emptyList()
86- ) { state ->
87- val jcExecutionConstruction = constructJcExecution(jcMachine, state, jcContainer)
88-
89- val jcExecution = jcExecutionConstruction.jcExecution
90- val executableId = jcExecution.method.method.toExecutableId(jcContainer.cp)
91-
92- val executionConverter = JcToUtExecutionConverter (
93- jcExecution = jcExecution,
94- jcClasspath = jcContainer.cp,
95- idGenerator = ReferencePreservingIntIdGenerator (),
96- instructionIdProvider = SimpleInstructionIdProvider (),
97- utilMethodProvider = UtilMethodProviderPlaceholder ,
73+ JcMachine (
74+ cp = jcContainer.cp,
75+ options = UMachineOptions (
76+ timeout = timeoutMillis.milliseconds,
77+ pathSelectionStrategies = listOf (PathSelectionStrategy .CLOSEST_TO_UNCOVERED_RANDOM ),
78+ pathSelectorFairnessStrategy = PathSelectorFairnessStrategy .COMPLETELY_FAIR ,
79+ solverType = SolverType .Z3 ,
9880 )
99-
100- val utResult = if (jcExecutionConstruction.useUsvmExecutor) {
101- executionConverter.convert()
102- } else {
103- val initialState = executionConverter.convertInitialStateOnly()
104- val concreteExecutor = ConcreteExecutor (concreteExecutionContext.instrumentationFactory, classpath)
105- .apply { this .classLoader = utContext.classLoader }
106-
107- runStandardConcreteExecution(concreteExecutor, executableId, initialState)
108- }
109-
110- utResult?.let {
111- analysisResult = AnalysisResult (executableId, it)
81+ ).use { jcMachine ->
82+ jcMachine.analyzeAsync(
83+ forceTerminationTimeout = (timeoutMillis * 1.1 + 2000 ).toLong(),
84+ methods = jcMethods,
85+ targets = emptyList()
86+ ) { state ->
87+ val jcExecution = constructJcExecution(jcMachine, state, jcContainer)
88+
89+ val executableId = jcExecution.method.method.toExecutableId(jcContainer.cp)
90+
91+ val executionConverter = JcToUtExecutionConverter (
92+ jcExecution = jcExecution,
93+ jcClasspath = jcContainer.cp,
94+ idGenerator = ReferencePreservingIntIdGenerator (),
95+ instructionIdProvider = SimpleInstructionIdProvider (),
96+ utilMethodProvider = UtilMethodProviderPlaceholder ,
97+ )
98+
99+ val utResult = runCatching {
100+ executionConverter.convert()
101+ }.getOrElse { e ->
102+ logger.warn(e) { " JcToUtExecutionConverter.convert(${jcExecution.method.method} ) failed" }
103+
104+ val initialState = executionConverter.convertInitialStateOnly()
105+ val concreteExecutor =
106+ ConcreteExecutor (concreteExecutionContext.instrumentationFactory, classpath)
107+ .apply { this .classLoader = utContext.classLoader }
108+
109+ runStandardConcreteExecution(concreteExecutor, executableId, initialState)
110+ }
111+
112+ utResult?.let {
113+ collectedExecutions.add(executableId to it)
114+ }
112115 }
113116 }
114117 }
115118
116- analysisResult?.let {
117- emit(it.executableId to it.utResult)
118- }
119+ return collectedExecutions
119120 }
120121
121122 private fun constructJcExecution (
122123 jcMachine : JcMachine ,
123124 state : JcState ,
124125 jcContainer : JcContainer ,
125- ): JcExecutionConstruction {
126+ ): JcExecution {
126127 val executor = JcTestExecutor (jcContainer.cp, jcContainer.runner)
127128
128129 val realJcExecution = runCatching {
@@ -133,16 +134,16 @@ object UsvmSymbolicEngine {
133134 classConstants = jcMachine.classConstants,
134135 allowSymbolicResult = false
135136 )
136- }.getOrElse { null }
137+ }.getOrElse { e ->
138+ logger.warn(e) { " executor.execute(${state.entrypoint} ) failed" }
139+ null
140+ }
137141
138142 realJcExecution?.let {
139- return JcExecutionConstruction (
140- jcExecution = it,
141- useUsvmExecutor = true ,
142- )
143+ return it
143144 }
144145
145- val jcExecutionWithUTest = JcExecution (
146+ return JcExecution (
146147 method = state.entrypoint.typedMethod,
147148 uTest = executor.createUTest(
148149 method = state.entrypoint.typedMethod,
@@ -153,11 +154,6 @@ object UsvmSymbolicEngine {
153154 uTestExecutionResultWrappers = emptySequence(),
154155 coverage = JcCoverage (emptyMap()),
155156 )
156-
157- return JcExecutionConstruction (
158- jcExecution = jcExecutionWithUTest,
159- useUsvmExecutor = false ,
160- )
161157 }
162158
163159 private fun runStandardConcreteExecution (
@@ -175,15 +171,17 @@ object UsvmSymbolicEngine {
175171 )
176172 }
177173
178- UtSymbolicExecution (
179- initialState.stateBefore,
180- concreteExecutionResult.stateAfter,
181- concreteExecutionResult.result,
182- concreteExecutionResult.newInstrumentation ? : initialState.instrumentations,
183- mutableListOf (),
184- listOf (),
185- concreteExecutionResult.coverage
186- )
174+ concreteExecutionResult.processedFailure()?.let { failure ->
175+ logger.warn { " Instrumented process failed with exception ${failure.exception} " +
176+ " before concrete execution started" }
177+ null
178+ } ? : UtUsvmExecution (
179+ initialState.stateBefore,
180+ concreteExecutionResult.stateAfter,
181+ concreteExecutionResult.result,
182+ concreteExecutionResult.coverage,
183+ instrumentation = concreteExecutionResult.newInstrumentation ? : initialState.instrumentations,
184+ )
187185 } catch (e: CancellationException ) {
188186 logger.debug(e) { " Cancellation happened" }
189187 null
@@ -203,17 +201,12 @@ object UsvmSymbolicEngine {
203201 classpath = classpathFiles,
204202 javaHome = JdkInfoService .provide().path.toFile(),
205203 ) {
206- installFeatures(InMemoryHierarchy , Approximations , ClassScorer (TypeScorer , ::scoreClassNode))
204+ installFeatures(
205+ InMemoryHierarchy ,
206+ Approximations ,
207+ // ApproximationPaths(JcJars.approximationsJar, ...)
208+ ClassScorer (TypeScorer , ::scoreClassNode)
209+ )
207210 loadByteCode(classpathFiles)
208211 }
209-
210- data class JcExecutionConstruction (
211- val jcExecution : JcExecution ,
212- val useUsvmExecutor : Boolean ,
213- )
214-
215- data class AnalysisResult (
216- val executableId : ExecutableId ,
217- val utResult : UtResult ,
218- )
219212}
0 commit comments