Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add way to get instrumentation result #2457

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.FieldId
import org.utbot.framework.plugin.api.ConcreteContextLoadingResult
import org.utbot.framework.plugin.api.SpringRepositoryId
import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.api.util.UtContext
import org.utbot.framework.plugin.api.util.signature
import org.utbot.instrumentation.instrumentation.Instrumentation
import org.utbot.instrumentation.instrumentation.execution.ResultOfInstrumentation
import org.utbot.instrumentation.process.generated.ComputeStaticFieldParams
import org.utbot.instrumentation.process.generated.GetResultOfInstrumentationParams
import org.utbot.instrumentation.process.generated.GetSpringRepositoriesParams
import org.utbot.instrumentation.process.generated.InvokeMethodCommandParams
import org.utbot.instrumentation.rd.InstrumentedProcess
Expand Down Expand Up @@ -313,3 +316,12 @@ fun <T> ConcreteExecutor<*, *>.computeStaticField(fieldId: FieldId): Result<T> =
kryoHelper.readObject(result.result)
}
}

fun ConcreteExecutor<*, *>.getInstrumentationResult(methodUnderTest: ExecutableId): ResultOfInstrumentation =
runBlocking {
withProcess {
val params = GetResultOfInstrumentationParams(methodUnderTest.classId.name, methodUnderTest.signature)
val result = instrumentedProcessModel.getResultOfInstrumentation.startSuspending(lifetime, params)
kryoHelper.readObject(result.result)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ data class PutStaticInstruction(

private data class ClassToMethod(
val className: String,
val methodName: String
val methodSignature: String
)

class ProcessingStorage {
Expand All @@ -65,6 +65,8 @@ class ProcessingStorage {
private val instructionsData = mutableMapOf<Long, InstructionData>()
private val classToInstructionsCount = mutableMapOf<String, Long>()

private val methodIdToInstructionsIds = mutableMapOf<Int, MutableList<Long>>()

fun addClass(className: String): Int {
val id = classToId.getOrPut(className) { classToId.size }
idToClass.putIfAbsent(id, className)
Expand All @@ -75,8 +77,8 @@ class ProcessingStorage {
return classToId[className]!!.toLong() * SHIFT + localId
}

fun addClassMethod(className: String, methodName: String): Int {
val classToMethod = ClassToMethod(className, methodName)
fun addClassMethod(className: String, methodSignature: String): Int {
val classToMethod = ClassToMethod(className, methodSignature)
val id = classMethodToId.getOrPut(classToMethod) { classMethodToId.size }
idToClassMethod.putIfAbsent(id, classToMethod)
return id
Expand All @@ -88,10 +90,11 @@ class ProcessingStorage {
return className to localId
}

fun addInstruction(id: Long, instructionData: InstructionData) {
fun addInstruction(id: Long, methodId: Int, instructionData: InstructionData) {
instructionsData.computeIfAbsent(id) {
val (className, _) = computeClassNameAndLocalId(id)
classToInstructionsCount.merge(className, 1, Long::plus)
methodIdToInstructionsIds.getOrPut(methodId) { mutableListOf() }.add(id)
instructionData
}
}
Expand All @@ -103,6 +106,11 @@ class ProcessingStorage {
return instructionsData.getValue(id)
}

fun getInstructionsIds(className: String, methodSignature: String): List<Long>? {
val methodId = classMethodToId[ClassToMethod(className, methodSignature)]
return methodIdToInstructionsIds[methodId]
}

companion object {
private const val SHIFT = 1.toLong().shl(32) // 2 ^ 32
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TraceListStrategy(
methodVisitor: MethodVisitor
) {
currentMethodSignature = name + descriptor
currentClassMethodId = storage.addClassMethod(className, name)
currentClassMethodId = storage.addClassMethod(className, currentMethodSignature)
}

override fun visitCode(mv: MethodVisitor, lvs: LocalVariablesSorter) {
Expand Down Expand Up @@ -74,7 +74,7 @@ class TraceListStrategy(

private fun processNewInstruction(mv: MethodVisitor, instructionData: InstructionData): MethodVisitor {
val id = nextId()
storage.addInstruction(id, instructionData)
storage.addInstruction(id, currentClassMethodId, instructionData)
return inserter.insertUtilityInstructions(mv, id)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class RemovingConstructFailsUtExecutionInstrumentation(
}
}

override fun getResultOfInstrumentation(className: String, methodSignature: String): ResultOfInstrumentation =
delegateInstrumentation.getResultOfInstrumentation(className, methodSignature)

private fun shallowlyRemoveFailingCalls(model: UtModel): UtModel = when {
model !is UtAssembleModel -> model
model.instantiationCall.thrownConcreteException != null -> model.classId.defaultValueModel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ class SimpleUtExecutionInstrumentation(
)
}

override fun getResultOfInstrumentation(className: String, methodSignature: String): ResultOfInstrumentation =
ResultOfInstrumentation(traceHandler.processingStorage.getInstructionsIds(className, methodSignature))

override fun getStaticField(fieldId: FieldId): Result<UtModel> =
delegateInstrumentation.getStaticField(fieldId).map { value ->
UtModelConstructor.createOnlyUserClassesConstructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ data class UtConcreteExecutionResult(
}
}

data class ResultOfInstrumentation(val instructionsIds: List<Long>?)

interface UtExecutionInstrumentation : Instrumentation<UtConcreteExecutionResult> {
override fun invoke(
clazz: Class<*>,
Expand All @@ -88,6 +90,8 @@ interface UtExecutionInstrumentation : Instrumentation<UtConcreteExecutionResult
phasesWrapper: PhasesController.(invokeBasePhases: () -> PreliminaryUtConcreteExecutionResult) -> PreliminaryUtConcreteExecutionResult
): UtConcreteExecutionResult

fun getResultOfInstrumentation(className: String, methodSignature: String): ResultOfInstrumentation

interface Factory<out TInstrumentation : UtExecutionInstrumentation> : Instrumentation.Factory<UtConcreteExecutionResult, TInstrumentation> {
override fun create(): TInstrumentation = create(SimpleInstrumentationContext())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.utbot.framework.plugin.api.util.SpringModelUtils.mockMvcPerformMethod
import org.utbot.framework.plugin.api.util.jClass
import org.utbot.framework.process.kryo.KryoHelper
import org.utbot.instrumentation.instrumentation.ArgumentList
import org.utbot.instrumentation.instrumentation.execution.ResultOfInstrumentation
import org.utbot.instrumentation.instrumentation.execution.PreliminaryUtConcreteExecutionResult
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionData
import org.utbot.instrumentation.instrumentation.execution.UtConcreteExecutionResult
Expand Down Expand Up @@ -118,6 +119,9 @@ class SpringUtExecutionInstrumentation(
}
}

override fun getResultOfInstrumentation(className: String, methodSignature: String): ResultOfInstrumentation =
delegateInstrumentation.getResultOfInstrumentation(className, methodSignature)

override fun getStaticField(fieldId: FieldId): Result<*> = delegateInstrumentation.getStaticField(fieldId)

private fun getRelevantBeans(clazz: Class<*>): Set<String> = relatedBeansCache.getOrPut(clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import org.utbot.framework.process.kryo.KryoHelper
import org.utbot.instrumentation.agent.Agent
import org.utbot.instrumentation.instrumentation.Instrumentation
import org.utbot.instrumentation.instrumentation.coverage.CoverageInstrumentation
import org.utbot.instrumentation.instrumentation.execution.UtExecutionInstrumentation
import org.utbot.instrumentation.process.generated.CollectCoverageResult
import org.utbot.instrumentation.process.generated.InstrumentedProcessModel
import org.utbot.instrumentation.process.generated.InvokeMethodCommandResult
import org.utbot.instrumentation.process.generated.instrumentedProcessModel
import org.utbot.instrumentation.process.generated.GetResultOfInstrumentationResult
import org.utbot.rd.IdleWatchdog
import org.utbot.rd.ClientProtocolBuilder
import org.utbot.rd.RdSettingsContainerFactory
Expand Down Expand Up @@ -146,6 +148,13 @@ private fun InstrumentedProcessModel.setup(kryoHelper: KryoHelper, watchdog: Idl
Agent.dynamicClassTransformer.addUserPaths(pathsToUserClasses)
instrumentation.run { setupAdditionalRdResponses(kryoHelper, watchdog) }
}
watchdog.measureTimeForActiveCall(getResultOfInstrumentation, "Getting instrumentation result") { params ->
HandlerClassesLoader.loadClass(params.className)
val result = (instrumentation as UtExecutionInstrumentation).getResultOfInstrumentation(
params.className, params.methodSignature
)
GetResultOfInstrumentationResult(kryoHelper.writeObject(result))
}
watchdog.measureTimeForActiveCall(addPaths, "User and dependency classpath setup") { params ->
pathsToUserClasses = params.pathsToUserClasses.split(File.pathSeparatorChar).toSet()
HandlerClassesLoader.addUrls(pathsToUserClasses)
Expand Down
Loading