From f535810193d0e3dd6e495ad6153decc965df01aa Mon Sep 17 00:00:00 2001 From: Dmitrii Timofeev Date: Mon, 4 Jul 2022 16:26:16 +0300 Subject: [PATCH] Initiate concrete execution if a wrapper method is missing If a JVM class is overridden but a method is missing from the wrapper, the engine will discard the path and fall back to concrete execution instead of analysing the real JVM code graph. This approach fixes the problem with methods that have been introduced in newer JDKs. Now wrappers are mostly limited to Java 1.8 interfaces and fail to analyze methods like `String::isBlank` or `String::lines` when the code runs under JDK 11. Building graphs from the real JDK code fails because the wrapper does not have private fields that the original code uses. TODO: to allow symbolic analysis of the code, missing methods should be actually implemented in corresponding wrappers. --- .../kotlin/org/utbot/engine/CollectionWrappers.kt | 14 ++++++++++---- .../kotlin/org/utbot/engine/UtBotSymbolicEngine.kt | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt index 602051458a..3aa0dff24d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt @@ -10,6 +10,7 @@ import org.utbot.engine.overrides.collections.UtHashSet import org.utbot.engine.overrides.collections.UtLinkedList import org.utbot.engine.pc.UtAddrExpression import org.utbot.engine.pc.UtExpression +import org.utbot.engine.pc.UtFalse import org.utbot.engine.pc.select import org.utbot.engine.symbolic.asHardConstraint import org.utbot.engine.z3.intValue @@ -84,10 +85,15 @@ abstract class BaseOverriddenWrapper(protected val overriddenClassName: String) val overriddenMethod = overriddenClass.findMethodOrNull(method.subSignature) - val jimpleBody = overriddenMethod?.jimpleBody() ?: method.jimpleBody() - val graphResult = GraphResult(jimpleBody.graph()) - - return listOf(graphResult) + if (overriddenMethod == null) { + // No overridden method has been found, switch to concrete execution + pathLogger.warn("Method ${overriddenClass.name}::${method.subSignature} not found, executing concretely") + return emptyList() + } else { + val jimpleBody = overriddenMethod.jimpleBody() + val graphResult = GraphResult(jimpleBody.graph()) + return listOf(graphResult) + } } } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt index 02c793d8f4..3b1ea942dd 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt @@ -3079,6 +3079,11 @@ class UtBotSymbolicEngine( instanceAsWrapperOrNull?.run { val results = invoke(instance as ObjectValue, invocation.method, invocation.parameters) + if (results.isEmpty()) { + // Drop the branch and switch to concrete execution + statesForConcreteExecution += environment.state + queuedSymbolicStateUpdates += UtFalse.asHardConstraint() + } return OverrideResult(success = true, results) }