Skip to content

Commit a38adc9

Browse files
IlyaMuravjovEgorkaKulikov
authored andcommitted
Make TestCaseGenerator use UsvmSymbolicEngine for entire class (#2716)
1 parent fcd7344 commit a38adc9

File tree

4 files changed

+58
-44
lines changed

4 files changed

+58
-44
lines changed

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ package org.utbot.engine
22

33
import kotlinx.coroutines.flow.Flow
44
import kotlinx.coroutines.flow.emptyFlow
5+
import org.utbot.framework.plugin.api.ExecutableId
56
import org.utbot.framework.plugin.api.UtResult
67

7-
class UsvmSymbolicEngine {
8-
9-
fun generateWithUsvm(): Flow<UtResult> = emptyFlow()
8+
object UsvmSymbolicEngine {
9+
// TODO implement
10+
fun runUsvmGeneration(
11+
methods: List<ExecutableId>,
12+
classpath: String,
13+
timeoutMillis: Long
14+
): Flow<Pair<ExecutableId, UtResult>> =
15+
emptyFlow()
1016
}

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

+32-24
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.catch
88
import kotlinx.coroutines.flow.emitAll
99
import kotlinx.coroutines.flow.flow
1010
import kotlinx.coroutines.flow.flowOf
11+
import kotlinx.coroutines.flow.map
1112
import kotlinx.coroutines.isActive
1213
import kotlinx.coroutines.launch
1314
import kotlinx.coroutines.yield
@@ -16,6 +17,7 @@ import mu.KotlinLogging
1617
import org.utbot.common.*
1718
import org.utbot.engine.EngineController
1819
import org.utbot.engine.Mocker
20+
import org.utbot.engine.UsvmSymbolicEngine
1921
import org.utbot.engine.UtBotSymbolicEngine
2022
import org.utbot.engine.util.mockListeners.ForceMockListener
2123
import org.utbot.engine.util.mockListeners.ForceStaticMockListener
@@ -173,9 +175,10 @@ open class TestCaseGenerator(
173175
methods: List<ExecutableId>,
174176
mockStrategy: MockStrategyApi,
175177
chosenClassesToMockAlways: Set<ClassId> = Mocker.javaDefaultClasses.mapTo(mutableSetOf()) { it.id },
176-
methodsGenerationTimeout: Long = utBotGenerationTimeoutInMillis,
178+
utBotTimeout: Long = utBotGenerationTimeoutInMillis,
177179
userTaintConfigurationProvider: TaintConfigurationProvider? = null,
178-
generate: (engine: UtBotSymbolicEngine) -> Flow<UtResult> = defaultTestFlow(methodsGenerationTimeout)
180+
generate: (engine: UtBotSymbolicEngine) -> Flow<UtResult> = defaultTestFlow(utBotTimeout),
181+
usvmTimeoutMillis: Long = 0,
179182
): List<UtMethodTestSet> = ConcreteExecutor.defaultPool.use { _ -> // TODO: think on appropriate way to close instrumented processes
180183
if (isCanceled()) return@use methods.map { UtMethodTestSet(it) }
181184

@@ -189,7 +192,7 @@ open class TestCaseGenerator(
189192
return@use methods.map { method -> UtMethodTestSet(method, errors = method2errors.getValue(method)) }
190193

191194
val executionStartInMillis = System.currentTimeMillis()
192-
val executionTimeEstimator = ExecutionTimeEstimator(methodsGenerationTimeout, methods.size)
195+
val executionTimeEstimator = ExecutionTimeEstimator(utBotTimeout, methods.size)
193196

194197
val currentUtContext = utContext
195198

@@ -200,6 +203,29 @@ open class TestCaseGenerator(
200203
val forceMockListener = ForceMockListener.create(this, conflictTriggers)
201204
val forceStaticMockListener = ForceStaticMockListener.create(this, conflictTriggers)
202205

206+
suspend fun consumeUtResultFlow(utResultFlow: Flow<Pair<ExecutableId, UtResult>>) =
207+
utResultFlow.catch {
208+
logger.error(it) { "Error in flow" }
209+
}
210+
.collect { (executableId, utResult) ->
211+
when (utResult) {
212+
is UtExecution -> {
213+
if (utResult is UtSymbolicExecution &&
214+
(conflictTriggers.triggered(Conflict.ForceMockHappened) ||
215+
conflictTriggers.triggered(Conflict.ForceStaticMockHappened))
216+
) {
217+
utResult.containsMocking = true
218+
}
219+
method2executions.getValue(executableId) += utResult
220+
}
221+
222+
is UtError -> {
223+
method2errors.getValue(executableId).merge(utResult.description, 1, Int::plus)
224+
logger.error(utResult.error) { "UtError occurred" }
225+
}
226+
}
227+
}
228+
203229
runIgnoringCancellationException {
204230
runBlockingWithCancellationPredicate(isCanceled) {
205231
for ((method, controller) in method2controller) {
@@ -223,27 +249,7 @@ open class TestCaseGenerator(
223249
engineActions.map { engine.apply(it) }
224250
engineActions.clear()
225251

226-
generate(engine)
227-
.catch {
228-
logger.error(it) { "Error in flow" }
229-
}
230-
.collect {
231-
when (it) {
232-
is UtExecution -> {
233-
if (it is UtSymbolicExecution &&
234-
(conflictTriggers.triggered(Conflict.ForceMockHappened) ||
235-
conflictTriggers.triggered(Conflict.ForceStaticMockHappened))
236-
) {
237-
it.containsMocking = true
238-
}
239-
method2executions.getValue(method) += it
240-
}
241-
is UtError -> {
242-
method2errors.getValue(method).merge(it.description, 1, Int::plus)
243-
logger.error(it.error) { "UtError occurred" }
244-
}
245-
}
246-
}
252+
consumeUtResultFlow(generate(engine).map { utResult -> method to utResult })
247253
} catch (e: Exception) {
248254
logger.error(e) {"Error in engine"}
249255
throw e
@@ -284,6 +290,8 @@ open class TestCaseGenerator(
284290
}
285291
logger.debug("test generator global scope lifecycle check ended")
286292
}
293+
294+
consumeUtResultFlow(UsvmSymbolicEngine.runUsvmGeneration(methods, classpathForEngine, usvmTimeoutMillis))
287295
}
288296
}
289297

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

+4-13
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import kotlinx.coroutines.flow.Flow
44
import kotlinx.coroutines.flow.emptyFlow
55
import kotlinx.coroutines.flow.flattenConcat
66
import kotlinx.coroutines.flow.flowOf
7-
import org.utbot.engine.UsvmSymbolicEngine
87
import org.utbot.engine.UtBotSymbolicEngine
98
import org.utbot.framework.UtSettings
10-
import org.utbot.framework.codegen.domain.SymbolicEngineSource
119

1210
/**
1311
* Constructs [TestFlow] for customization and creates flow producer.
@@ -18,8 +16,7 @@ fun testFlow(block: TestFlow.() -> Unit): UtBotSymbolicEngine.() -> Flow<UtResul
1816
* Creates default flow that uses [UtSettings] for customization.
1917
*/
2018
fun defaultTestFlow(timeout: Long) = testFlow {
21-
isSymbolicEngineEnabled = true
22-
symbolicEngineType = SymbolicEngineSource.UnitTestBot
19+
isUtBotSymbolicEngineEnabled = true
2320
generationTimeout = timeout
2421
isFuzzingEnabled = UtSettings.useFuzzing
2522
if (generationTimeout > 0) {
@@ -42,8 +39,7 @@ class TestFlow internal constructor(block: TestFlow.() -> Unit) {
4239
set(value) {
4340
field = maxOf(0, value)
4441
}
45-
var isSymbolicEngineEnabled = true
46-
var symbolicEngineType = SymbolicEngineSource.UnitTestBot
42+
var isUtBotSymbolicEngineEnabled = true
4743
var isFuzzingEnabled = false
4844
var fuzzingValue: Double = 0.1
4945
set(value) {
@@ -64,7 +60,7 @@ class TestFlow internal constructor(block: TestFlow.() -> Unit) {
6460
return when {
6561
generationTimeout == 0L -> emptyFlow()
6662
isFuzzingEnabled -> {
67-
when (val value = if (isSymbolicEngineEnabled) (fuzzingValue * generationTimeout).toLong() else generationTimeout) {
63+
when (val value = if (isUtBotSymbolicEngineEnabled) (fuzzingValue * generationTimeout).toLong() else generationTimeout) {
6864
0L -> engine.traverse()
6965
generationTimeout -> engine.fuzzing(System.currentTimeMillis() + value)
7066
else -> flowOf(
@@ -73,12 +69,7 @@ class TestFlow internal constructor(block: TestFlow.() -> Unit) {
7369
).flattenConcat()
7470
}
7571
}
76-
isSymbolicEngineEnabled -> {
77-
when (symbolicEngineType) {
78-
SymbolicEngineSource.UnitTestBot -> engine.traverse()
79-
SymbolicEngineSource.Usvm -> UsvmSymbolicEngine().generateWithUsvm()
80-
}
81-
}
72+
isUtBotSymbolicEngineEnabled -> engine.traverse()
8273
else -> emptyFlow()
8374
}
8475
}

utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt

+13-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import org.utbot.framework.codegen.domain.ParametrizedTestSource
1313
import org.utbot.framework.codegen.domain.ProjectType
1414
import org.utbot.framework.codegen.domain.RuntimeExceptionTestsBehaviour
1515
import org.utbot.framework.codegen.domain.SymbolicEngineSource
16+
import org.utbot.framework.codegen.domain.SymbolicEngineSource.*
1617
import org.utbot.framework.codegen.domain.testFrameworkByName
1718
import org.utbot.framework.codegen.generator.AbstractCodeGenerator
1819
import org.utbot.framework.codegen.generator.CodeGeneratorParams
@@ -114,10 +115,17 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch
114115
val methods: List<ExecutableId> = kryoHelper.readObject(params.methods)
115116
logger.debug()
116117
.measureTime({ "starting generation for ${methods.size} methods, starting with ${methods.first()}" }) {
118+
val symbolicEngineSource = SymbolicEngineSource.valueOf(params.symbolicEngineType)
119+
val utBotTimeout = when {
120+
!params.isSymbolicEngineEnabled -> params.timeout
121+
symbolicEngineSource == UnitTestBot -> params.timeout
122+
params.isFuzzingEnabled -> (params.fuzzingValue * params.timeout).toLong()
123+
else -> 0L
124+
}
125+
117126
val generateFlow = testFlow {
118-
generationTimeout = params.generationTimeout
119-
isSymbolicEngineEnabled = params.isSymbolicEngineEnabled
120-
symbolicEngineType = SymbolicEngineSource.valueOf(params.symbolicEngineType)
127+
generationTimeout = utBotTimeout
128+
isUtBotSymbolicEngineEnabled = params.isSymbolicEngineEnabled && symbolicEngineSource == UnitTestBot
121129
isFuzzingEnabled = params.isFuzzingEnabled
122130
fuzzingValue = params.fuzzingValue
123131
}
@@ -130,9 +138,10 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch
130138
methods,
131139
MockStrategyApi.valueOf(params.mockStrategy),
132140
kryoHelper.readObject(params.chosenClassesToMockAlways),
133-
params.timeout,
141+
utBotTimeout,
134142
userTaintConfigurationProvider,
135143
generate = generateFlow,
144+
usvmTimeoutMillis = params.generationTimeout - utBotTimeout,
136145
)
137146
.summarizeAll(Paths.get(params.searchDirectory), null)
138147
.filterNot { it.executions.isEmpty() && it.errors.isEmpty() }

0 commit comments

Comments
 (0)