11package org.utbot.framework.concrete
22
3- import org.objectweb.asm.Type
4- import org.utbot.common.StopWatch
5- import org.utbot.common.ThreadBasedExecutor
6- import org.utbot.common.withAccessibility
3+ import java.security.ProtectionDomain
4+ import java.util.IdentityHashMap
5+ import kotlin.reflect.jvm.javaMethod
76import org.utbot.framework.UtSettings
87import org.utbot.framework.assemble.AssembleModelGenerator
8+ import org.utbot.framework.concrete.constructors.ConstructOnlyUserClassesOrCachedObjectsStrategy
9+ import org.utbot.framework.concrete.constructors.UtModelConstructor
10+ import org.utbot.framework.concrete.mock.InstrumentationContext
11+ import org.utbot.framework.concrete.phases.PhasesController
12+ import org.utbot.framework.concrete.phases.start
913import org.utbot.framework.plugin.api.Coverage
1014import org.utbot.framework.plugin.api.EnvironmentModels
1115import org.utbot.framework.plugin.api.FieldId
12- import org.utbot.framework.plugin.api.Instruction
13- import org.utbot.framework.plugin.api.MissingState
14- import org.utbot.framework.plugin.api.TimeoutException
1516import org.utbot.framework.plugin.api.UtAssembleModel
16- import org.utbot.framework.plugin.api.UtExecutionFailure
1717import org.utbot.framework.plugin.api.UtExecutionResult
1818import org.utbot.framework.plugin.api.UtExecutionSuccess
19- import org.utbot.framework.plugin.api.UtExplicitlyThrownException
20- import org.utbot.framework.plugin.api.UtImplicitlyThrownException
2119import org.utbot.framework.plugin.api.UtInstrumentation
2220import org.utbot.framework.plugin.api.UtModel
23- import org.utbot.framework.plugin.api.UtNewInstanceInstrumentation
24- import org.utbot.framework.plugin.api.UtSandboxFailure
25- import org.utbot.framework.plugin.api.UtStaticMethodInstrumentation
26- import org.utbot.framework.plugin.api.visible.UtStreamConsumingException
27- import org.utbot.framework.plugin.api.UtStreamConsumingFailure
28- import org.utbot.framework.plugin.api.UtTimeoutException
29- import org.utbot.framework.plugin.api.util.UtContext
30- import org.utbot.framework.plugin.api.util.id
31- import org.utbot.framework.plugin.api.util.jField
3221import org.utbot.framework.plugin.api.util.singleExecutableId
33- import org.utbot.framework.plugin.api.util.utContext
34- import org.utbot.framework.plugin.api.util.withUtContext
35- import org.utbot.framework.util.isInaccessibleViaReflection
3622import org.utbot.instrumentation.instrumentation.ArgumentList
3723import org.utbot.instrumentation.instrumentation.Instrumentation
3824import org.utbot.instrumentation.instrumentation.InvokeInstrumentation
39- import org.utbot.instrumentation.instrumentation.et.EtInstruction
40- import org.utbot.instrumentation.instrumentation.et.ExplicitThrowInstruction
4125import org.utbot.instrumentation.instrumentation.et.TraceHandler
4226import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
4327import org.utbot.instrumentation.instrumentation.mock.MockClassVisitor
44- import java.security.AccessControlException
45- import java.security.ProtectionDomain
46- import java.util.IdentityHashMap
47- import kotlin.reflect.jvm.javaMethod
4828
4929/* *
5030 * Consists of the data needed to execute the method concretely. Also includes method arguments stored in models.
@@ -142,107 +122,78 @@ object UtExecutionInstrumentation : Instrumentation<UtConcreteExecutionResult> {
142122 throw IllegalArgumentException (" Argument parameters must be of type UtConcreteExecutionData, but was: ${parameters?.javaClass} " )
143123 }
144124 val (stateBefore, instrumentations, timeout) = parameters // smart cast to UtConcreteExecutionData
145- val parametersModels = listOfNotNull(stateBefore.thisInstance) + stateBefore.parameters
146125
147126 val methodId = clazz.singleExecutableId(methodSignature)
148127 val returnClassId = methodId.returnType
149- traceHandler.resetTrace()
150-
151- return MockValueConstructor (instrumentationContext).use { constructor ->
152- val params = try {
153- constructor .constructMethodParameters(parametersModels)
154- } catch (e: Throwable ) {
155- if (e.cause is AccessControlException ) {
156- return @use UtConcreteExecutionResult (
157- MissingState ,
158- UtSandboxFailure (e.cause!! ),
159- Coverage ()
160- )
161- }
162128
163- throw e
129+ return PhasesController (
130+ instrumentationContext,
131+ traceHandler,
132+ delegateInstrumentation
133+ ).computeConcreteExecutionResult {
134+ // construction
135+ val (params, statics, cache) = valueConstructionContext.start {
136+ val params = constructParameters(stateBefore)
137+ val statics = constructStatics(stateBefore)
138+
139+ mock(instrumentations)
140+
141+ Triple (params, statics, getCache())
164142 }
165- val staticFields = constructor
166- .constructStatics(
167- stateBefore
168- .statics
169- .filterKeys { ! it.isInaccessibleViaReflection }
170- )
171- .mapValues { (_, value) -> value.value }
172-
173- val concreteExecutionResult = withStaticFields(staticFields) {
174- val staticMethodsInstrumentation = instrumentations.filterIsInstance<UtStaticMethodInstrumentation >()
175- constructor .mockStaticMethods(staticMethodsInstrumentation)
176- val newInstanceInstrumentation = instrumentations.filterIsInstance<UtNewInstanceInstrumentation >()
177- constructor .mockNewInstances(newInstanceInstrumentation)
178-
179- traceHandler.resetTrace()
180- val stopWatch = StopWatch ()
181- val context = UtContext (utContext.classLoader, stopWatch)
182- val concreteResult = ThreadBasedExecutor .threadLocal.invokeWithTimeout(timeout, stopWatch) {
183- withUtContext(context) {
184- delegateInstrumentation.invoke(clazz, methodSignature, params.map { it.value })
185- }
186- }?.getOrThrow() as ? Result <* > ? : Result .failure<Any ?>(TimeoutException (" Timeout $timeout elapsed" ))
187- val traceList = traceHandler.computeInstructionList()
188-
189- val cache = constructor .objectToModelCache
190- val utCompositeModelStrategy = ConstructOnlyUserClassesOrCachedObjectsStrategy (pathsToUserClasses, cache)
191- val utModelConstructor = UtModelConstructor (cache, utCompositeModelStrategy)
192- utModelConstructor.run {
193- val concreteUtModelResult = concreteResult.fold({
194- try {
195- val model = construct(it, returnClassId)
196- UtExecutionSuccess (model)
197- } catch (e: Exception ) {
198- processExceptionDuringModelConstruction(e)
199- }
200- }) {
201- sortOutException(it)
143+
144+ // preparation
145+ val savedStatics = preparationContext.start {
146+ val savedStatics = setStaticFields(statics)
147+ resetTrace()
148+ savedStatics
149+ }
150+
151+ try {
152+ // invocation
153+ val concreteResult = invocationContext.start {
154+ invoke(clazz, methodSignature, params.map { it.value }, timeout)
155+ }
156+
157+ // statistics collection
158+ val coverage = statisticsCollectionContext.start {
159+ getCoverage(clazz)
160+ }
161+
162+ // model construction
163+ val (executionResult, stateAfter) = modelConstructionContext.start {
164+ configureConstructor {
165+ this .cache = cache
166+ strategy = ConstructOnlyUserClassesOrCachedObjectsStrategy (pathsToUserClasses, cache)
202167 }
203168
204- val stateAfterParametersWithThis = params.map { construct(it.value, it.clazz.id) }
205- val stateAfterStatics = (staticFields.keys/* + traceHandler.computePutStatics()*/ )
206- .associateWith { fieldId ->
207- fieldId.jField.run {
208- val computedValue = withAccessibility { get(null ) }
209- val knownModel = stateBefore.statics[fieldId]
210- val knownValue = staticFields[fieldId]
211- if (knownModel != null && knownValue != null && knownValue == computedValue) {
212- knownModel
213- } else {
214- construct(computedValue, fieldId.type)
215- }
216- }
217- }
169+ val executionResult = convertToExecutionResult(concreteResult, returnClassId)
170+
171+ val stateAfterParametersWithThis = constructParameters(params)
172+ val stateAfterStatics = constructStatics(statics.keys/* + traceHandler.computePutStatics()*/ )
218173 val (stateAfterThis, stateAfterParameters) = if (stateBefore.thisInstance == null ) {
219174 null to stateAfterParametersWithThis
220175 } else {
221176 stateAfterParametersWithThis.first() to stateAfterParametersWithThis.drop(1 )
222177 }
223178 val stateAfter = EnvironmentModels (stateAfterThis, stateAfterParameters, stateAfterStatics)
224- UtConcreteExecutionResult (
225- stateAfter,
226- concreteUtModelResult,
227- traceList.toApiCoverage(
228- traceHandler.processingStorage.getInstructionsCount(
229- Type .getInternalName(clazz)
230- )
231- )
232- )
179+
180+ executionResult to stateAfter
233181 }
234- }
235182
236- concreteExecutionResult
183+ UtConcreteExecutionResult (
184+ stateAfter,
185+ executionResult,
186+ coverage
187+ )
188+ } finally {
189+ // postprocessing
190+ postprocessingContext.start {
191+ resetStaticFields(savedStatics)
192+ }
193+ }
237194 }
238195 }
239196
240- private fun processExceptionDuringModelConstruction (e : Exception ): UtExecutionResult =
241- when (e) {
242- is UtStreamConsumingException -> UtStreamConsumingFailure (e)
243- else -> throw e
244- }
245-
246197 override fun getStaticField (fieldId : FieldId ): Result <UtModel > =
247198 delegateInstrumentation.getStaticField(fieldId).map { value ->
248199 val cache = IdentityHashMap <Any , UtModel >()
@@ -254,30 +205,6 @@ object UtExecutionInstrumentation : Instrumentation<UtConcreteExecutionResult> {
254205 }
255206 }
256207
257- private fun sortOutException (exception : Throwable ): UtExecutionFailure {
258- if (exception is TimeoutException ) {
259- return UtTimeoutException (exception)
260- }
261- if (exception is AccessControlException ||
262- exception is ExceptionInInitializerError && exception.exception is AccessControlException ) {
263- return UtSandboxFailure (exception)
264- }
265- // there also can be other cases, when we need to wrap internal exception... I suggest adding them on demand
266-
267- val instrs = traceHandler.computeInstructionList()
268- val isNested = if (instrs.isEmpty()) {
269- false
270- } else {
271- instrs.first().callId != instrs.last().callId
272- }
273- return if (instrs.isNotEmpty() && instrs.last().instructionData is ExplicitThrowInstruction ) {
274- UtExplicitlyThrownException (exception, isNested)
275- } else {
276- UtImplicitlyThrownException (exception, isNested)
277- }
278-
279- }
280-
281208 override fun transform (
282209 loader : ClassLoader ? ,
283210 className : String ,
@@ -305,36 +232,4 @@ object UtExecutionInstrumentation : Instrumentation<UtConcreteExecutionResult> {
305232
306233 return instrumenter.classByteCode
307234 }
308-
309- private fun <T > withStaticFields (staticFields : Map <FieldId , Any ?>, block : () -> T ): T {
310- val savedFields = mutableMapOf<FieldId , Any ?>()
311- try {
312- staticFields.forEach { (fieldId, value) ->
313- fieldId.jField.run {
314- withAccessibility {
315- savedFields[fieldId] = get(null )
316- set(null , value)
317- }
318- }
319- }
320- return block()
321- } finally {
322- savedFields.forEach { (fieldId, value) ->
323- fieldId.jField.run {
324- withAccessibility {
325- set(null , value)
326- }
327- }
328- }
329- }
330- }
331235}
332-
333- /* *
334- * Transforms a list of internal [EtInstruction]s to a list of api [Instruction]s.
335- */
336- private fun List<EtInstruction>.toApiCoverage (instructionsCount : Long? = null): Coverage =
337- Coverage (
338- map { Instruction (it.className, it.methodSignature, it.line, it.id) },
339- instructionsCount
340- )
0 commit comments