1
1
package org.utbot.framework.codegen.model.constructor.tree
2
2
3
3
import org.utbot.common.PathUtil
4
+ import org.utbot.common.WorkaroundReason
4
5
import org.utbot.common.isStatic
6
+ import org.utbot.common.workaround
5
7
import org.utbot.framework.assemble.assemble
6
8
import org.utbot.framework.codegen.ForceStaticMocking
7
9
import org.utbot.framework.codegen.ParametrizedTestSource
@@ -146,7 +148,8 @@ import java.lang.reflect.InvocationTargetException
146
148
import java.security.AccessControlException
147
149
import java.lang.reflect.ParameterizedType
148
150
import 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
150
153
import org.utbot.framework.plugin.api.util.allSuperTypes
151
154
import org.utbot.framework.plugin.api.util.baseStreamClassId
152
155
import org.utbot.framework.plugin.api.util.doubleStreamClassId
@@ -182,6 +185,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
182
185
183
186
private val fieldsOfExecutionResults = mutableMapOf<Pair <FieldId , Int >, MutableList <UtModel >>()
184
187
188
+ /* *
189
+ * Contains whether [UtStreamConsumingFailure] is in [CgMethodTestSet] for parametrized tests.
190
+ * See [WorkaroundReason.CONSUME_DIRTY_STREAMS].
191
+ */
192
+ private var containsStreamConsumingFailureForParametrizedTests: Boolean = false
193
+
185
194
private fun setupInstrumentation () {
186
195
if (currentExecution is UtSymbolicExecution ) {
187
196
val execution = currentExecution as UtSymbolicExecution
@@ -299,28 +308,30 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
299
308
emptyLineIfNeeded()
300
309
val method = currentExecutable as MethodId
301
310
val currentExecution = currentExecution!!
311
+ val executionResult = currentExecution.result
312
+
302
313
// build assertions
303
- currentExecution.result
304
- .onSuccess { result ->
314
+ executionResult
315
+ .onSuccess { resultModel ->
305
316
methodType = SUCCESSFUL
306
317
307
- // TODO possible engine bug - void method return type and result not UtVoidModel
308
- if (result .isUnit() || method.returnType == voidClassId) {
318
+ // TODO possible engine bug - void method return type and result model not UtVoidModel
319
+ if (resultModel .isUnit() || method.returnType == voidClassId) {
309
320
+ thisInstance[method](* methodArguments.toTypedArray())
310
321
} else {
311
- resultModel = result
312
- val expected = variableConstructor.getOrCreateVariable(result , " expected" )
322
+ this . resultModel = resultModel
323
+ val expected = variableConstructor.getOrCreateVariable(resultModel , " expected" )
313
324
assertEquality(expected, actual)
314
325
}
315
326
}
316
- .onFailure { exception -> processExecutionFailure(exception) }
327
+ .onFailure { exception -> processExecutionFailure(exception, executionResult ) }
317
328
}
318
329
else -> {} // TODO: check this specific case
319
330
}
320
331
}
321
332
322
- private fun processExecutionFailure (exceptionFromAnalysis : Throwable ) {
323
- val (methodInvocationBlock, expectedException) = constructExceptionProducingBlock(exceptionFromAnalysis)
333
+ private fun processExecutionFailure (exceptionFromAnalysis : Throwable , executionResult : UtExecutionResult ) {
334
+ val (methodInvocationBlock, expectedException) = constructExceptionProducingBlock(exceptionFromAnalysis, executionResult )
324
335
325
336
when (methodType) {
326
337
SUCCESSFUL -> error(" Unexpected successful without exception method type for execution with exception $expectedException " )
@@ -354,9 +365,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
354
365
}
355
366
}
356
367
357
- private fun constructExceptionProducingBlock (exceptionFromAnalysis : Throwable ): Pair <() -> Unit , Throwable> {
358
- if (exceptionFromAnalysis is UtStreamConsumingException ) {
359
- return constructStreamConsumingBlock() to exceptionFromAnalysis.innerExceptionOrAny
368
+ private fun constructExceptionProducingBlock (
369
+ exceptionFromAnalysis : Throwable ,
370
+ executionResult : UtExecutionResult
371
+ ): Pair <() -> Unit , Throwable> {
372
+ if (executionResult is UtStreamConsumingFailure ) {
373
+ return constructStreamConsumingBlock() to executionResult.rootCauseException
360
374
}
361
375
362
376
return {
@@ -460,22 +474,32 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
460
474
is ConstructorId -> generateConstructorCall(currentExecutable!! , currentExecution!! )
461
475
is MethodId -> {
462
476
val method = currentExecutable as MethodId
463
- currentExecution!! .result
464
- .onSuccess { result ->
465
- if (result.isUnit()) {
477
+ val executionResult = currentExecution!! .result
478
+
479
+ executionResult
480
+ .onSuccess { resultModel ->
481
+ if (resultModel.isUnit()) {
466
482
+ thisInstance[method](* methodArguments.toTypedArray())
467
483
} else {
468
484
// "generic" expected variable is represented with a wrapper if
469
485
// actual result is primitive to support cases with exceptions.
470
- resultModel = if (result is UtPrimitiveModel ) assemble(result ) else result
486
+ this . resultModel = if (resultModel is UtPrimitiveModel ) assemble(resultModel ) else resultModel
471
487
472
488
val expectedVariable = currentMethodParameters[CgParameterKind .ExpectedResult ]!!
473
489
val expectedExpression = CgNotNullAssertion (expectedVariable)
474
490
475
491
assertEquality(expectedExpression, actual)
476
492
}
477
493
}
478
- .onFailure { thisInstance[method](* methodArguments.toTypedArray()).intercepted() }
494
+ .onFailure {
495
+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
496
+ if (containsStreamConsumingFailureForParametrizedTests) {
497
+ constructStreamConsumingBlock().invoke()
498
+ } else {
499
+ thisInstance[method](* methodArguments.toTypedArray()).intercepted()
500
+ }
501
+ }
502
+ }
479
503
}
480
504
else -> {} // TODO: check this specific case
481
505
}
@@ -1207,7 +1231,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1207
1231
// we cannot generate any assertions for constructor testing
1208
1232
// but we need to generate a constructor call
1209
1233
val constructorCall = currentExecutableId as ConstructorId
1210
- currentExecution.result
1234
+ val executionResult = currentExecution.result
1235
+
1236
+ executionResult
1211
1237
.onSuccess {
1212
1238
methodType = SUCCESSFUL
1213
1239
@@ -1219,7 +1245,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1219
1245
constructorCall(* methodArguments.toTypedArray())
1220
1246
}
1221
1247
}
1222
- .onFailure { exception -> processExecutionFailure(exception) }
1248
+ .onFailure { exception -> processExecutionFailure(exception, executionResult ) }
1223
1249
}
1224
1250
1225
1251
/* *
@@ -1240,7 +1266,15 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1240
1266
actual.type.isPrimitive -> generateDeepEqualsAssertion(expected, actual)
1241
1267
else -> ifStatement(
1242
1268
CgEqualTo (expected, nullLiteral()),
1243
- trueBranch = { + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement() },
1269
+ trueBranch = {
1270
+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
1271
+ if (containsStreamConsumingFailureForParametrizedTests) {
1272
+ constructStreamConsumingBlock().invoke()
1273
+ } else {
1274
+ + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement()
1275
+ }
1276
+ }
1277
+ },
1244
1278
falseBranch = {
1245
1279
+ testFrameworkManager.assertions[testFrameworkManager.assertNotNull](actual).toStatement()
1246
1280
generateDeepEqualsAssertion(expected, actual)
@@ -1269,21 +1303,23 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1269
1303
}
1270
1304
1271
1305
private fun recordActualResult () {
1272
- currentExecution!! .result.onSuccess { result ->
1306
+ val executionResult = currentExecution!! .result
1307
+
1308
+ executionResult.onSuccess { resultModel ->
1273
1309
when (val executable = currentExecutable) {
1274
1310
is ConstructorId -> {
1275
1311
// there is nothing to generate for constructors
1276
1312
return
1277
1313
}
1278
1314
is BuiltinMethodId -> error(" Unexpected BuiltinMethodId $currentExecutable while generating actual result" )
1279
1315
is MethodId -> {
1280
- // TODO possible engine bug - void method return type and result not UtVoidModel
1281
- if (result .isUnit() || executable.returnType == voidClassId) return
1316
+ // TODO possible engine bug - void method return type and result model not UtVoidModel
1317
+ if (resultModel .isUnit() || executable.returnType == voidClassId) return
1282
1318
1283
1319
emptyLineIfNeeded()
1284
1320
1285
1321
actual = newVar(
1286
- CgClassId (result .classId, isNullable = result is UtNullModel ),
1322
+ CgClassId (resultModel .classId, isNullable = resultModel is UtNullModel ),
1287
1323
" actual"
1288
1324
) {
1289
1325
thisInstance[executable](* methodArguments.toTypedArray())
@@ -1292,13 +1328,13 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1292
1328
else -> {} // TODO: check this specific case
1293
1329
}
1294
1330
}.onFailure {
1295
- processActualInvocationFailure(it )
1331
+ processActualInvocationFailure(executionResult )
1296
1332
}
1297
1333
}
1298
1334
1299
- private fun processActualInvocationFailure (e : Throwable ) {
1300
- when (e ) {
1301
- is UtStreamConsumingException -> processStreamConsumingException(e.innerExceptionOrAny )
1335
+ private fun processActualInvocationFailure (executionResult : UtExecutionResult ) {
1336
+ when (executionResult ) {
1337
+ is UtStreamConsumingFailure -> processStreamConsumingException(executionResult.rootCauseException )
1302
1338
else -> {} // Do nothing for now
1303
1339
}
1304
1340
}
@@ -1419,6 +1455,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1419
1455
// may be a heuristic to select a model with minimal number of internal nulls should be used
1420
1456
val genericExecution = chooseGenericExecution(testSet.executions)
1421
1457
1458
+ workaround(WorkaroundReason .CONSUME_DIRTY_STREAMS ) {
1459
+ containsStreamConsumingFailureForParametrizedTests = testSet.executions.any {
1460
+ it.result is UtStreamConsumingFailure
1461
+ }
1462
+ }
1463
+
1422
1464
val statics = genericExecution.stateBefore.statics
1423
1465
1424
1466
return withTestMethodScope(genericExecution) {
0 commit comments