|
8 | 8 |
|
9 | 9 | package org.utbot.framework.plugin.api
|
10 | 10 |
|
11 |
| -import mu.KotlinLogging |
12 | 11 | import org.utbot.common.FileUtil
|
13 | 12 | import org.utbot.common.isDefaultValue
|
14 | 13 | import org.utbot.common.withToStringThreadLocalReentrancyGuard
|
@@ -56,17 +55,8 @@ import java.io.File
|
56 | 55 | import kotlin.contracts.ExperimentalContracts
|
57 | 56 | import kotlin.contracts.contract
|
58 | 57 | import org.utbot.common.isAbstract
|
59 |
| -import org.utbot.common.isStatic |
60 |
| -import org.utbot.framework.isFromTrustedLibrary |
61 |
| -import org.utbot.framework.plugin.api.TypeReplacementMode.* |
62 | 58 | import org.utbot.framework.plugin.api.util.SpringModelUtils
|
63 |
| -import org.utbot.framework.plugin.api.util.allDeclaredFieldIds |
64 |
| -import org.utbot.framework.plugin.api.util.allSuperTypes |
65 |
| -import org.utbot.framework.plugin.api.util.fieldId |
66 |
| -import org.utbot.framework.plugin.api.util.isSubtypeOf |
67 |
| -import org.utbot.framework.plugin.api.util.utContext |
68 | 59 | import org.utbot.framework.process.OpenModulesContainer
|
69 |
| -import soot.SootField |
70 | 60 | import soot.SootMethod
|
71 | 61 |
|
72 | 62 | const val SYMBOLIC_NULL_ADDR: Int = 0
|
@@ -1332,71 +1322,6 @@ interface SpringCodeGenerationContext : CodeGenerationContext {
|
1332 | 1322 | val springContextLoadingResult: SpringContextLoadingResult?
|
1333 | 1323 | }
|
1334 | 1324 |
|
1335 |
| -/** |
1336 |
| - * A context to use when no specific data is required. |
1337 |
| - * |
1338 |
| - * @param mockFrameworkInstalled shows if we have installed framework dependencies |
1339 |
| - * @param staticsMockingIsConfigured shows if we have installed static mocking tools |
1340 |
| - */ |
1341 |
| -open class ApplicationContext( |
1342 |
| - val mockFrameworkInstalled: Boolean = true, |
1343 |
| - staticsMockingIsConfigured: Boolean = true, |
1344 |
| -) : CodeGenerationContext { |
1345 |
| - var staticsMockingIsConfigured = staticsMockingIsConfigured |
1346 |
| - private set |
1347 |
| - |
1348 |
| - init { |
1349 |
| - /** |
1350 |
| - * Situation when mock framework is not installed but static mocking is configured is semantically incorrect. |
1351 |
| - * |
1352 |
| - * However, it may be obtained in real application after this actions: |
1353 |
| - * - fully configure mocking (dependency installed + resource file created) |
1354 |
| - * - remove mockito-core dependency from project |
1355 |
| - * - forget to remove mock-maker file from resource directory |
1356 |
| - * |
1357 |
| - * Here we transform this configuration to semantically correct. |
1358 |
| - */ |
1359 |
| - if (!mockFrameworkInstalled && staticsMockingIsConfigured) { |
1360 |
| - this.staticsMockingIsConfigured = false |
1361 |
| - } |
1362 |
| - } |
1363 |
| - |
1364 |
| - /** |
1365 |
| - * Shows if there are any restrictions on type implementors. |
1366 |
| - */ |
1367 |
| - open val typeReplacementMode: TypeReplacementMode = AnyImplementor |
1368 |
| - |
1369 |
| - /** |
1370 |
| - * Finds a type to replace the original abstract type |
1371 |
| - * if it is guided with some additional information. |
1372 |
| - */ |
1373 |
| - open fun replaceTypeIfNeeded(type: RefType): ClassId? = null |
1374 |
| - |
1375 |
| - /** |
1376 |
| - * Sets the restrictions on speculative not null |
1377 |
| - * constraints in current application context. |
1378 |
| - * |
1379 |
| - * @see docs/SpeculativeFieldNonNullability.md for more information. |
1380 |
| - */ |
1381 |
| - open fun avoidSpeculativeNotNullChecks(field: SootField): Boolean = |
1382 |
| - UtSettings.maximizeCoverageUsingReflection || !field.declaringClass.isFromTrustedLibrary() |
1383 |
| - |
1384 |
| - /** |
1385 |
| - * Checks whether accessing [field] (with a method invocation or field access) speculatively |
1386 |
| - * cannot produce [NullPointerException] (according to its finality or accessibility). |
1387 |
| - * |
1388 |
| - * @see docs/SpeculativeFieldNonNullability.md for more information. |
1389 |
| - */ |
1390 |
| - open fun speculativelyCannotProduceNullPointerException( |
1391 |
| - field: SootField, |
1392 |
| - classUnderTest: ClassId, |
1393 |
| - ): Boolean = field.isFinal || !field.isPublic |
1394 |
| - |
1395 |
| - open fun preventsFurtherTestGeneration(): Boolean = false |
1396 |
| - |
1397 |
| - open fun getErrors(): List<UtError> = emptyList() |
1398 |
| -} |
1399 |
| - |
1400 | 1325 | sealed class SpringConfiguration(val fullDisplayName: String) {
|
1401 | 1326 | class JavaConfiguration(val classBinaryName: String) : SpringConfiguration(classBinaryName)
|
1402 | 1327 | class XMLConfiguration(val absolutePath: String) : SpringConfiguration(absolutePath)
|
@@ -1429,139 +1354,6 @@ class SpringContextLoadingResult(
|
1429 | 1354 | val exceptions: List<Throwable>
|
1430 | 1355 | )
|
1431 | 1356 |
|
1432 |
| -/** |
1433 |
| - * Data we get from Spring application context |
1434 |
| - * to manage engine and code generator behaviour. |
1435 |
| - * |
1436 |
| - * @param beanDefinitions describes bean definitions (bean name, type, some optional additional data) |
1437 |
| - * @param shouldUseImplementors describes it we want to replace interfaces with injected types or not |
1438 |
| - */ |
1439 |
| -// TODO move this class to utbot-framework so we can use it as abstract factory |
1440 |
| -// to get rid of numerous `when`s and polymorphically create things like: |
1441 |
| -// - Instrumentation<UtConcreteExecutionResult> |
1442 |
| -// - FuzzedType (to get rid of thisInstanceFuzzedTypeWrapper) |
1443 |
| -// - JavaValueProvider |
1444 |
| -// - CgVariableConstructor |
1445 |
| -// - CodeGeneratorResult (generateForSpringClass) |
1446 |
| -// Right now this refactoring is blocked because some interfaces need to get extracted and moved to utbot-framework-api |
1447 |
| -// As an alternative we can just move ApplicationContext itself to utbot-framework |
1448 |
| -class SpringApplicationContext( |
1449 |
| - mockInstalled: Boolean, |
1450 |
| - staticsMockingIsConfigured: Boolean, |
1451 |
| - val beanDefinitions: List<BeanDefinitionData> = emptyList(), |
1452 |
| - private val shouldUseImplementors: Boolean, |
1453 |
| - override val springTestType: SpringTestType, |
1454 |
| - override val springSettings: SpringSettings, |
1455 |
| -): ApplicationContext(mockInstalled, staticsMockingIsConfigured), SpringCodeGenerationContext { |
1456 |
| - |
1457 |
| - override var springContextLoadingResult: SpringContextLoadingResult? = null |
1458 |
| - |
1459 |
| - companion object { |
1460 |
| - private val logger = KotlinLogging.logger {} |
1461 |
| - } |
1462 |
| - |
1463 |
| - private var areInjectedClassesInitialized : Boolean = false |
1464 |
| - private var areAllInjectedTypesInitialized: Boolean = false |
1465 |
| - |
1466 |
| - // Classes representing concrete types that are actually used in Spring application |
1467 |
| - private val springInjectedClasses: Set<ClassId> |
1468 |
| - get() { |
1469 |
| - if (!areInjectedClassesInitialized) { |
1470 |
| - for (beanTypeName in beanDefinitions.map { it.beanTypeName }) { |
1471 |
| - try { |
1472 |
| - val beanClass = utContext.classLoader.loadClass(beanTypeName) |
1473 |
| - if (!beanClass.isAbstract && !beanClass.isInterface && |
1474 |
| - !beanClass.isLocalClass && (!beanClass.isMemberClass || beanClass.isStatic)) { |
1475 |
| - springInjectedClassesStorage += beanClass.id |
1476 |
| - } |
1477 |
| - } catch (e: Throwable) { |
1478 |
| - // For some Spring beans (e.g. with anonymous classes) |
1479 |
| - // it is possible to have problems with classes loading. |
1480 |
| - when (e) { |
1481 |
| - is ClassNotFoundException, is NoClassDefFoundError, is IllegalAccessError -> |
1482 |
| - logger.warn { "Failed to load bean class for $beanTypeName (${e.message})" } |
1483 |
| - |
1484 |
| - else -> throw e |
1485 |
| - } |
1486 |
| - } |
1487 |
| - } |
1488 |
| - |
1489 |
| - // This is done to be sure that this storage is not empty after the first class loading iteration. |
1490 |
| - // So, even if all loaded classes were filtered out, we will not try to load them again. |
1491 |
| - areInjectedClassesInitialized = true |
1492 |
| - } |
1493 |
| - |
1494 |
| - return springInjectedClassesStorage |
1495 |
| - } |
1496 |
| - |
1497 |
| - private val allInjectedTypes: Set<ClassId> |
1498 |
| - get() { |
1499 |
| - if (!areAllInjectedTypesInitialized) { |
1500 |
| - allInjectedTypesStorage = springInjectedClasses.flatMap { it.allSuperTypes() }.toSet() |
1501 |
| - areAllInjectedTypesInitialized = true |
1502 |
| - } |
1503 |
| - |
1504 |
| - return allInjectedTypesStorage |
1505 |
| - } |
1506 |
| - |
1507 |
| - // imitates `by lazy` (we can't use actual `by lazy` because communication via RD breaks it) |
1508 |
| - private var allInjectedTypesStorage: Set<ClassId> = emptySet() |
1509 |
| - |
1510 |
| - // This is a service field to model the lazy behavior of [springInjectedClasses]. |
1511 |
| - // Do not call it outside the getter. |
1512 |
| - // |
1513 |
| - // Actually, we should just call [springInjectedClasses] with `by lazy`, but we had problems |
1514 |
| - // with a strange `kotlin.UNINITIALIZED_VALUE` in `speculativelyCannotProduceNullPointerException` method call. |
1515 |
| - private val springInjectedClassesStorage = mutableSetOf<ClassId>() |
1516 |
| - |
1517 |
| - override val typeReplacementMode: TypeReplacementMode = |
1518 |
| - if (shouldUseImplementors) KnownImplementor else NoImplementors |
1519 |
| - |
1520 |
| - /** |
1521 |
| - * Replaces an interface type with its implementor type |
1522 |
| - * if there is the unique implementor in bean definitions. |
1523 |
| - */ |
1524 |
| - override fun replaceTypeIfNeeded(type: RefType): ClassId? = |
1525 |
| - if (type.isAbstractType) { |
1526 |
| - springInjectedClasses.singleOrNull { it.isSubtypeOf(type.id) } |
1527 |
| - } else { |
1528 |
| - null |
1529 |
| - } |
1530 |
| - |
1531 |
| - override fun avoidSpeculativeNotNullChecks(field: SootField): Boolean = false |
1532 |
| - |
1533 |
| - /** |
1534 |
| - * In Spring applications we can mark as speculatively not null |
1535 |
| - * fields if they are mocked and injecting into class under test so on. |
1536 |
| - * |
1537 |
| - * Fields are not mocked if their actual type is obtained from [springInjectedClasses]. |
1538 |
| - * |
1539 |
| - */ |
1540 |
| - override fun speculativelyCannotProduceNullPointerException( |
1541 |
| - field: SootField, |
1542 |
| - classUnderTest: ClassId, |
1543 |
| - ): Boolean = field.fieldId in classUnderTest.allDeclaredFieldIds && field.type.classId !in allInjectedTypes |
1544 |
| - |
1545 |
| - override fun preventsFurtherTestGeneration(): Boolean = |
1546 |
| - super.preventsFurtherTestGeneration() || springContextLoadingResult?.contextLoaded == false |
1547 |
| - |
1548 |
| - override fun getErrors(): List<UtError> = |
1549 |
| - springContextLoadingResult?.exceptions?.map { exception -> |
1550 |
| - UtError( |
1551 |
| - "Failed to load Spring application context", |
1552 |
| - exception |
1553 |
| - ) |
1554 |
| - }.orEmpty() + super.getErrors() |
1555 |
| - |
1556 |
| - fun getBeansAssignableTo(classId: ClassId): List<BeanDefinitionData> = beanDefinitions.filter { beanDef -> |
1557 |
| - // some bean classes may fail to load |
1558 |
| - runCatching { |
1559 |
| - val beanClass = ClassId(beanDef.beanTypeName).jClass |
1560 |
| - classId.jClass.isAssignableFrom(beanClass) |
1561 |
| - }.getOrElse { false } |
1562 |
| - } |
1563 |
| -} |
1564 |
| - |
1565 | 1357 | enum class SpringTestType(
|
1566 | 1358 | override val id: String,
|
1567 | 1359 | override val displayName: String,
|
|
0 commit comments