@@ -10,6 +10,7 @@ import org.utbot.analytics.Predictors
10
10
import org.utbot.api.exception.UtMockAssumptionViolatedException
11
11
import org.utbot.common.debug
12
12
import org.utbot.common.measureTime
13
+ import org.utbot.common.tryLoadClass
13
14
import org.utbot.engine.MockStrategy.NO_MOCKS
14
15
import org.utbot.engine.pc.*
15
16
import org.utbot.engine.selectors.*
@@ -33,7 +34,7 @@ import org.utbot.framework.UtSettings.pathSelectorType
33
34
import org.utbot.framework.UtSettings.processUnknownStatesDuringConcreteExecution
34
35
import org.utbot.framework.UtSettings.useDebugVisualization
35
36
import org.utbot.framework.context.ApplicationContext
36
- import org.utbot.framework.context.ConcreteExecutionContext
37
+ import org.utbot.framework.context.spring.SpringApplicationContext
37
38
import org.utbot.framework.plugin.api.*
38
39
import org.utbot.framework.plugin.api.Step
39
40
import org.utbot.framework.plugin.api.util.*
@@ -43,11 +44,17 @@ import org.utbot.framework.util.graph
43
44
import org.utbot.framework.util.sootMethod
44
45
import org.utbot.fuzzer.*
45
46
import org.utbot.fuzzing.*
47
+ import org.utbot.fuzzing.providers.FieldValueProvider
48
+ import org.utbot.fuzzing.providers.ObjectValueProvider
49
+ import org.utbot.fuzzing.spring.SavedEntityValueProvider
50
+ import org.utbot.fuzzing.spring.SpringBeanValueProvider
46
51
import org.utbot.fuzzing.utils.Trie
47
52
import org.utbot.instrumentation.ConcreteExecutor
53
+ import org.utbot.instrumentation.getRelevantSpringRepositories
48
54
import org.utbot.instrumentation.instrumentation.Instrumentation
49
55
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionData
50
56
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionResult
57
+ import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrumentation
51
58
import org.utbot.taint.*
52
59
import org.utbot.taint.model.TaintConfiguration
53
60
import soot.jimple.Stmt
@@ -111,7 +118,7 @@ class UtBotSymbolicEngine(
111
118
val mockStrategy : MockStrategy = NO_MOCKS ,
112
119
chosenClassesToMockAlways : Set <ClassId >,
113
120
val applicationContext : ApplicationContext ,
114
- val concreteExecutionContext : ConcreteExecutionContext ,
121
+ executionInstrumentationFactory : UtExecutionInstrumentation . Factory < * > ,
115
122
userTaintConfigurationProvider : TaintConfigurationProvider ? = null ,
116
123
private val solverTimeoutInMillis : Int = checkSolverTimeoutMillis,
117
124
) : UtContextInitializer() {
@@ -184,7 +191,7 @@ class UtBotSymbolicEngine(
184
191
185
192
private val concreteExecutor =
186
193
ConcreteExecutor (
187
- concreteExecutionContext.instrumentationFactory ,
194
+ executionInstrumentationFactory ,
188
195
classpath,
189
196
).apply { this .classLoader = utContext.classLoader }
190
197
@@ -386,15 +393,57 @@ class UtBotSymbolicEngine(
386
393
val names = graph.body.method.tags.filterIsInstance<ParamNamesTag >().firstOrNull()?.names ? : emptyList()
387
394
var testEmittedByFuzzer = 0
388
395
389
- val valueProviders = try {
390
- concreteExecutionContext.tryCreateValueProvider(concreteExecutor, classUnderTest, defaultIdGenerator)
391
- } catch (e: Exception ) {
392
- emit(UtError (e.message ? : " Failed to create ValueProvider" , e))
396
+ if (applicationContext is SpringApplicationContext &&
397
+ applicationContext.springTestType == SpringTestType .INTEGRATION_TEST &&
398
+ applicationContext.getBeansAssignableTo(methodUnderTest.classId).isEmpty()) {
399
+ val fullConfigDisplayName = (applicationContext.springSettings as ? SpringSettings .PresentSpringSettings )
400
+ ?.configuration?.fullDisplayName
401
+ val errorDescription = " No beans of type ${methodUnderTest.classId.name} are found. " +
402
+ " Try choosing different Spring configuration or adding beans to $fullConfigDisplayName "
403
+ emit(UtError (
404
+ errorDescription,
405
+ IllegalStateException (errorDescription)
406
+ ))
393
407
return @flow
394
- }. let (transform)
408
+ }
395
409
396
- val coverageToMinStateBeforeSize = mutableMapOf<Trie .Node <Instruction >, Int > ()
410
+ val valueProviders = ValueProvider .of(defaultValueProviders(defaultIdGenerator))
411
+ .letIf(applicationContext is SpringApplicationContext
412
+ && applicationContext.springTestType == SpringTestType .INTEGRATION_TEST
413
+ ) { provider ->
414
+ val relevantRepositories = concreteExecutor.getRelevantSpringRepositories(methodUnderTest.classId)
415
+ logger.info { " Detected relevant repositories for class ${methodUnderTest.classId} : $relevantRepositories " }
397
416
417
+ val generatedValueAnnotationClasses = SpringModelUtils .generatedValueClassIds.mapNotNull {
418
+ @Suppress(" UNCHECKED_CAST" ) // type system fails to understand that GeneratedValue is indeed an annotation
419
+ utContext.classLoader.tryLoadClass(it.name) as Class <out Annotation >?
420
+ }
421
+
422
+ val generatedValueFieldIds =
423
+ relevantRepositories
424
+ .map { it.entityClassId.jClass }
425
+ .flatMap { entityClass -> generateSequence(entityClass) { it.superclass } }
426
+ .flatMap { it.declaredFields.toList() }
427
+ .filter { field -> generatedValueAnnotationClasses.any { field.isAnnotationPresent(it) } }
428
+ .map { it.fieldId }
429
+ logger.info { " Detected @GeneratedValue fields: $generatedValueFieldIds " }
430
+
431
+ // spring should try to generate bean values, but if it fails, then object value provider is used for it
432
+ val springBeanValueProvider = SpringBeanValueProvider (
433
+ defaultIdGenerator,
434
+ beanNameProvider = { classId ->
435
+ (applicationContext as SpringApplicationContext ).getBeansAssignableTo(classId)
436
+ .map { it.beanName }
437
+ },
438
+ relevantRepositories = relevantRepositories
439
+ ).withFallback(ObjectValueProvider (defaultIdGenerator))
440
+ provider
441
+ .except { p -> p is ObjectValueProvider }
442
+ .with (springBeanValueProvider)
443
+ .with (ValueProvider .of(relevantRepositories.map { SavedEntityValueProvider (defaultIdGenerator, it) }))
444
+ .with (ValueProvider .of(generatedValueFieldIds.map { FieldValueProvider (defaultIdGenerator, it) }))
445
+ }.let (transform)
446
+ val coverageToMinStateBeforeSize = mutableMapOf<Trie .Node <Instruction >, Int > ()
398
447
runJavaFuzzing(
399
448
defaultIdGenerator,
400
449
methodUnderTest,
0 commit comments