Skip to content

Commit 46c10b3

Browse files
Add an option to process methods without a body (#1719)
1 parent 9b22a39 commit 46c10b3

File tree

2 files changed

+33
-3
lines changed
  • utbot-framework-api/src/main/kotlin/org/utbot/framework
  • utbot-framework/src/main/kotlin/org/utbot/engine

2 files changed

+33
-3
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,19 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
499499
* Note that values processed concretely won't be replaced with unbounded symbolic variables.
500500
*/
501501
var processAllClinitSectionsConcretely by getBooleanProperty(false)
502+
503+
/**
504+
* In cases where we don't have a body for a method, we can either throw an exception
505+
* or treat this a method as a source of an unbounded symbolic variable returned as a result.
506+
*
507+
* If this option is set in true, instead of analysis we will return an unbounded symbolic
508+
* variable with a corresponding type. Otherwise, an exception will be thrown.
509+
*
510+
* Default value is false since it is not a common situation when you cannot retrieve a body
511+
* from a regular method. Setting this option in true might be suitable in situations when
512+
* it is more important not to fall at all rather than work precisely.
513+
*/
514+
var treatAbsentMethodsAsUnboundedValue by getBooleanProperty(false)
502515
}
503516

504517
/**

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ import org.utbot.framework.plugin.api.util.utContext
134134
import org.utbot.framework.util.executableId
135135
import org.utbot.framework.util.graph
136136
import org.utbot.framework.plugin.api.util.isInaccessibleViaReflection
137+
import org.utbot.summary.ast.declaredClassName
137138
import java.lang.reflect.ParameterizedType
138139
import kotlin.collections.plus
139140
import kotlin.collections.plusAssign
@@ -2953,9 +2954,25 @@ class Traverser(
29532954
declaringClass == utArrayMockClass -> utArrayMockInvoke(target, parameters)
29542955
isUtMockForbidClassCastException -> isUtMockDisableClassCastExceptionCheckInvoke(parameters)
29552956
else -> {
2956-
val graph = substitutedMethod?.jimpleBody()?.graph() ?: jimpleBody().graph()
2957-
pushToPathSelector(graph, target.instance, parameters, target.constraints, isLibraryMethod)
2958-
emptyList()
2957+
// Try to extract a body from substitution of our method or from the method itself.
2958+
// For the substitution, if it exists, we have a corresponding body and graph,
2959+
// but for the method itself its body might not be present in the memory.
2960+
// This may happen because of classloading issues (e.g. absence of required library JAR file)
2961+
val graph = (substitutedMethod ?: this).takeIf { it.canRetrieveBody() }?.jimpleBody()?.graph()
2962+
2963+
if (graph != null) {
2964+
// If we have a graph to analyze, do it
2965+
pushToPathSelector(graph, target.instance, parameters, target.constraints, isLibraryMethod)
2966+
emptyList()
2967+
} else {
2968+
// Otherwise, depending on [treatAbsentMethodsAsUnboundedValue] either throw an exception
2969+
// or continue analysis with an unbounded variable as a result of the [this] method
2970+
if (UtSettings.treatAbsentMethodsAsUnboundedValue) {
2971+
listOf(unboundedVariable("methodWithoutBodyResult", method = this))
2972+
} else {
2973+
error("Cannot retrieve body for a $declaredClassName.$name method")
2974+
}
2975+
}
29592976
}
29602977
}
29612978
}

0 commit comments

Comments
 (0)