11package org.utbot.framework.codegen.model.constructor.tree
22
33import org.utbot.common.PathUtil
4+ import org.utbot.common.WorkaroundReason
45import org.utbot.common.isStatic
6+ import org.utbot.common.workaround
57import org.utbot.framework.assemble.assemble
68import org.utbot.framework.codegen.ForceStaticMocking
79import org.utbot.framework.codegen.ParametrizedTestSource
@@ -146,7 +148,8 @@ import java.lang.reflect.InvocationTargetException
146148import java.security.AccessControlException
147149import java.lang.reflect.ParameterizedType
148150import org.utbot.framework.UtSettings
149- import org.utbot.framework.plugin.api.UtStreamConsumingException
151+ import org.utbot.framework.plugin.api.UtExecutionResult
152+ import org.utbot.framework.plugin.api.UtStreamConsumingFailure
150153import org.utbot.framework.plugin.api.util.allSuperTypes
151154import org.utbot.framework.plugin.api.util.baseStreamClassId
152155import org.utbot.framework.plugin.api.util.doubleStreamClassId
@@ -183,6 +186,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
183186
184187 private val fieldsOfExecutionResults = mutableMapOf<Pair <FieldId , Int >, MutableList <UtModel >>()
185188
189+ /* *
190+ * Contains whether [UtStreamConsumingFailure] is in [CgMethodTestSet] for parametrized tests.
191+ * See [WorkaroundReason.CONSUME_DIRTY_STREAMS].
192+ */
193+ private var containsStreamConsumingFailureForParametrizedTests: Boolean = false
194+
186195 private fun setupInstrumentation () {
187196 if (currentExecution is UtSymbolicExecution ) {
188197 val execution = currentExecution as UtSymbolicExecution
@@ -300,28 +309,30 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
300309 emptyLineIfNeeded()
301310 val method = currentExecutable as MethodId
302311 val currentExecution = currentExecution!!
312+ val executionResult = currentExecution.result
313+
303314 // build assertions
304- currentExecution.result
305- .onSuccess { result ->
315+ executionResult
316+ .onSuccess { resultModel ->
306317 methodType = SUCCESSFUL
307318
308- // TODO possible engine bug - void method return type and result not UtVoidModel
309- if (result .isUnit() || method.returnType == voidClassId) {
319+ // TODO possible engine bug - void method return type and result model not UtVoidModel
320+ if (resultModel .isUnit() || method.returnType == voidClassId) {
310321 + thisInstance[method](* methodArguments.toTypedArray())
311322 } else {
312- resultModel = result
313- val expected = variableConstructor.getOrCreateVariable(result , " expected" )
323+ this . resultModel = resultModel
324+ val expected = variableConstructor.getOrCreateVariable(resultModel , " expected" )
314325 assertEquality(expected, actual)
315326 }
316327 }
317- .onFailure { exception -> processExecutionFailure(exception) }
328+ .onFailure { exception -> processExecutionFailure(exception, executionResult ) }
318329 }
319330 else -> {} // TODO: check this specific case
320331 }
321332 }
322333
323- private fun processExecutionFailure (exceptionFromAnalysis : Throwable ) {
324- val (methodInvocationBlock, expectedException) = constructExceptionProducingBlock(exceptionFromAnalysis)
334+ private fun processExecutionFailure (exceptionFromAnalysis : Throwable , executionResult : UtExecutionResult ) {
335+ val (methodInvocationBlock, expectedException) = constructExceptionProducingBlock(exceptionFromAnalysis, executionResult )
325336
326337 when (methodType) {
327338 SUCCESSFUL -> error(" Unexpected successful without exception method type for execution with exception $expectedException " )
@@ -355,9 +366,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
355366 }
356367 }
357368
358- private fun constructExceptionProducingBlock (exceptionFromAnalysis : Throwable ): Pair <() -> Unit , Throwable> {
359- if (exceptionFromAnalysis is UtStreamConsumingException ) {
360- return constructStreamConsumingBlock() to exceptionFromAnalysis.innerExceptionOrAny
369+ private fun constructExceptionProducingBlock (
370+ exceptionFromAnalysis : Throwable ,
371+ executionResult : UtExecutionResult
372+ ): Pair <() -> Unit , Throwable> {
373+ if (executionResult is UtStreamConsumingFailure ) {
374+ return constructStreamConsumingBlock() to executionResult.rootCauseException
361375 }
362376
363377 return {
@@ -461,22 +475,32 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
461475 is ConstructorId -> generateConstructorCall(currentExecutable!! , currentExecution!! )
462476 is MethodId -> {
463477 val method = currentExecutable as MethodId
464- currentExecution!! .result
465- .onSuccess { result ->
466- if (result.isUnit()) {
478+ val executionResult = currentExecution!! .result
479+
480+ executionResult
481+ .onSuccess { resultModel ->
482+ if (resultModel.isUnit()) {
467483 + thisInstance[method](* methodArguments.toTypedArray())
468484 } else {
469485 // "generic" expected variable is represented with a wrapper if
470486 // actual result is primitive to support cases with exceptions.
471- resultModel = if (result is UtPrimitiveModel ) assemble(result ) else result
487+ this . resultModel = if (resultModel is UtPrimitiveModel ) assemble(resultModel ) else resultModel
472488
473489 val expectedVariable = currentMethodParameters[CgParameterKind .ExpectedResult ]!!
474490 val expectedExpression = CgNotNullAssertion (expectedVariable)
475491
476492 assertEquality(expectedExpression, actual)
477493 }
478494 }
479- .onFailure { thisInstance[method](* methodArguments.toTypedArray()).intercepted() }
495+ .onFailure {
496+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
497+ if (containsStreamConsumingFailureForParametrizedTests) {
498+ constructStreamConsumingBlock().invoke()
499+ } else {
500+ thisInstance[method](* methodArguments.toTypedArray()).intercepted()
501+ }
502+ }
503+ }
480504 }
481505 else -> {} // TODO: check this specific case
482506 }
@@ -1208,7 +1232,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12081232 // we cannot generate any assertions for constructor testing
12091233 // but we need to generate a constructor call
12101234 val constructorCall = currentExecutableId as ConstructorId
1211- currentExecution.result
1235+ val executionResult = currentExecution.result
1236+
1237+ executionResult
12121238 .onSuccess {
12131239 methodType = SUCCESSFUL
12141240
@@ -1220,7 +1246,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12201246 constructorCall(* methodArguments.toTypedArray())
12211247 }
12221248 }
1223- .onFailure { exception -> processExecutionFailure(exception) }
1249+ .onFailure { exception -> processExecutionFailure(exception, executionResult ) }
12241250 }
12251251
12261252 /* *
@@ -1241,7 +1267,15 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12411267 actual.type.isPrimitive -> generateDeepEqualsAssertion(expected, actual)
12421268 else -> ifStatement(
12431269 CgEqualTo (expected, nullLiteral()),
1244- trueBranch = { + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement() },
1270+ trueBranch = {
1271+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
1272+ if (containsStreamConsumingFailureForParametrizedTests) {
1273+ constructStreamConsumingBlock().invoke()
1274+ } else {
1275+ + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement()
1276+ }
1277+ }
1278+ },
12451279 falseBranch = {
12461280 + testFrameworkManager.assertions[testFrameworkManager.assertNotNull](actual).toStatement()
12471281 generateDeepEqualsAssertion(expected, actual)
@@ -1270,21 +1304,23 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12701304 }
12711305
12721306 private fun recordActualResult () {
1273- currentExecution!! .result.onSuccess { result ->
1307+ val executionResult = currentExecution!! .result
1308+
1309+ executionResult.onSuccess { resultModel ->
12741310 when (val executable = currentExecutable) {
12751311 is ConstructorId -> {
12761312 // there is nothing to generate for constructors
12771313 return
12781314 }
12791315 is BuiltinMethodId -> error(" Unexpected BuiltinMethodId $currentExecutable while generating actual result" )
12801316 is MethodId -> {
1281- // TODO possible engine bug - void method return type and result not UtVoidModel
1282- if (result .isUnit() || executable.returnType == voidClassId) return
1317+ // TODO possible engine bug - void method return type and result model not UtVoidModel
1318+ if (resultModel .isUnit() || executable.returnType == voidClassId) return
12831319
12841320 emptyLineIfNeeded()
12851321
12861322 actual = newVar(
1287- CgClassId (result .classId, isNullable = result is UtNullModel ),
1323+ CgClassId (resultModel .classId, isNullable = resultModel is UtNullModel ),
12881324 " actual"
12891325 ) {
12901326 thisInstance[executable](* methodArguments.toTypedArray())
@@ -1293,13 +1329,13 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12931329 else -> {} // TODO: check this specific case
12941330 }
12951331 }.onFailure {
1296- processActualInvocationFailure(it )
1332+ processActualInvocationFailure(executionResult )
12971333 }
12981334 }
12991335
1300- private fun processActualInvocationFailure (e : Throwable ) {
1301- when (e ) {
1302- is UtStreamConsumingException -> processStreamConsumingException(e.innerExceptionOrAny )
1336+ private fun processActualInvocationFailure (executionResult : UtExecutionResult ) {
1337+ when (executionResult ) {
1338+ is UtStreamConsumingFailure -> processStreamConsumingException(executionResult.rootCauseException )
13031339 else -> {} // Do nothing for now
13041340 }
13051341 }
@@ -1423,6 +1459,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
14231459 // may be a heuristic to select a model with minimal number of internal nulls should be used
14241460 val genericExecution = chooseGenericExecution(testSet.executions)
14251461
1462+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
1463+ containsStreamConsumingFailureForParametrizedTests = testSet.executions.any {
1464+ it.result is UtStreamConsumingFailure
1465+ }
1466+ }
1467+
14261468 val statics = genericExecution.stateBefore.statics
14271469
14281470 return withTestMethodScope(genericExecution) {
0 commit comments