@@ -37,7 +37,6 @@ import org.utbot.framework.codegen.model.tree.CgExecutableCall
37
37
import org.utbot.framework.codegen.model.tree.CgExpression
38
38
import org.utbot.framework.codegen.model.tree.CgFieldAccess
39
39
import org.utbot.framework.codegen.model.tree.CgGetJavaClass
40
- import org.utbot.framework.codegen.model.tree.CgIsInstance
41
40
import org.utbot.framework.codegen.model.tree.CgLiteral
42
41
import org.utbot.framework.codegen.model.tree.CgMethod
43
42
import org.utbot.framework.codegen.model.tree.CgMethodCall
@@ -111,9 +110,10 @@ import org.utbot.framework.plugin.api.UtStaticMethodInstrumentation
111
110
import org.utbot.framework.plugin.api.UtSymbolicExecution
112
111
import org.utbot.framework.plugin.api.UtTimeoutException
113
112
import org.utbot.framework.plugin.api.UtVoidModel
113
+ import org.utbot.framework.plugin.api.isNotNull
114
+ import org.utbot.framework.plugin.api.isNull
114
115
import org.utbot.framework.plugin.api.onFailure
115
116
import org.utbot.framework.plugin.api.onSuccess
116
- import org.utbot.framework.plugin.api.util.booleanClassId
117
117
import org.utbot.framework.plugin.api.util.doubleArrayClassId
118
118
import org.utbot.framework.plugin.api.util.doubleClassId
119
119
import org.utbot.framework.plugin.api.util.doubleWrapperClassId
@@ -144,7 +144,6 @@ import org.utbot.summary.SummarySentenceConstants.TAB
144
144
import java.lang.reflect.InvocationTargetException
145
145
import java.security.AccessControlException
146
146
import java.lang.reflect.ParameterizedType
147
- import kotlin.reflect.jvm.javaType
148
147
149
148
private const val DEEP_EQUALS_MAX_DEPTH = 5 // TODO move it to plugin settings?
150
149
@@ -168,6 +167,8 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
168
167
169
168
private lateinit var methodType: CgTestMethodType
170
169
170
+ private val fieldsOfExecutionResults = mutableMapOf<Pair <FieldId , Int >, MutableList <UtModel >>()
171
+
171
172
private fun setupInstrumentation () {
172
173
if (currentExecution is UtSymbolicExecution ) {
173
174
val execution = currentExecution as UtSymbolicExecution
@@ -445,7 +446,6 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
445
446
val expectedExpression = CgNotNullAssertion (expectedVariable)
446
447
447
448
assertEquality(expectedExpression, actual)
448
- println ()
449
449
}
450
450
}
451
451
.onFailure { thisInstance[method](* methodArguments.toTypedArray()).intercepted() }
@@ -537,7 +537,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
537
537
doubleDelta
538
538
)
539
539
expectedModel.value is Boolean -> {
540
- when (parameterizedTestSource ) {
540
+ when (parametrizedTestSource ) {
541
541
ParametrizedTestSource .DO_NOT_PARAMETRIZE ->
542
542
if (expectedModel.value as Boolean ) {
543
543
assertions[assertTrue](actual)
@@ -842,6 +842,25 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
842
842
return
843
843
}
844
844
845
+ when (parametrizedTestSource) {
846
+ ParametrizedTestSource .DO_NOT_PARAMETRIZE -> {
847
+ traverseField(fieldId, fieldModel, expected, actual, depth, visitedModels)
848
+ }
849
+
850
+ ParametrizedTestSource .PARAMETRIZE -> {
851
+ traverseFieldForParametrizedTest(fieldId, fieldModel, expected, actual, depth, visitedModels)
852
+ }
853
+ }
854
+ }
855
+
856
+ private fun traverseField (
857
+ fieldId : FieldId ,
858
+ fieldModel : UtModel ,
859
+ expected : CgVariable ,
860
+ actual : CgVariable ,
861
+ depth : Int ,
862
+ visitedModels : MutableSet <UtModel >
863
+ ) {
845
864
// fieldModel is not visited and will be marked in assertDeepEquals call
846
865
val fieldName = fieldId.name
847
866
var expectedVariable: CgVariable ? = null
@@ -866,6 +885,140 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
866
885
emptyLineIfNeeded()
867
886
}
868
887
888
+ private fun traverseFieldForParametrizedTest (
889
+ fieldId : FieldId ,
890
+ fieldModel : UtModel ,
891
+ expected : CgVariable ,
892
+ actual : CgVariable ,
893
+ depth : Int ,
894
+ visitedModels : MutableSet <UtModel >
895
+ ) {
896
+ val fieldResultModels = fieldsOfExecutionResults[fieldId to depth]
897
+ val nullResultModelInExecutions = fieldResultModels?.find { it.isNull() }
898
+ val notNullResultModelInExecutions = fieldResultModels?.find { it.isNotNull() }
899
+
900
+ val hasNullResultModel = nullResultModelInExecutions != null
901
+ val hasNotNullResultModel = notNullResultModelInExecutions != null
902
+
903
+ val needToSubstituteFieldModel = fieldModel is UtNullModel && hasNotNullResultModel
904
+
905
+ val fieldModelForAssert = if (needToSubstituteFieldModel) notNullResultModelInExecutions!! else fieldModel
906
+
907
+ // fieldModel is not visited and will be marked in assertDeepEquals call
908
+ val fieldName = fieldId.name
909
+ var expectedVariable: CgVariable ? = null
910
+
911
+ val needExpectedDeclaration = needExpectedDeclaration(fieldModelForAssert)
912
+ if (needExpectedDeclaration) {
913
+ val expectedFieldDeclaration = createDeclarationForFieldFromVariable(fieldId, expected, fieldName)
914
+
915
+ currentBlock + = expectedFieldDeclaration
916
+ expectedVariable = expectedFieldDeclaration.variable
917
+ }
918
+
919
+ val actualFieldDeclaration = createDeclarationForFieldFromVariable(fieldId, actual, fieldName)
920
+ currentBlock + = actualFieldDeclaration
921
+
922
+ if (needExpectedDeclaration && hasNullResultModel) {
923
+ ifStatement(
924
+ CgEqualTo (expectedVariable!! , nullLiteral()),
925
+ trueBranch = { + testFrameworkManager.assertions[testFramework.assertNull](actualFieldDeclaration.variable).toStatement() },
926
+ falseBranch = {
927
+ assertDeepEquals(
928
+ fieldModelForAssert,
929
+ expectedVariable,
930
+ actualFieldDeclaration.variable,
931
+ depth + 1 ,
932
+ visitedModels,
933
+ )
934
+ }
935
+ )
936
+ } else {
937
+ assertDeepEquals(
938
+ fieldModelForAssert,
939
+ expectedVariable,
940
+ actualFieldDeclaration.variable,
941
+ depth + 1 ,
942
+ visitedModels,
943
+ )
944
+ }
945
+ emptyLineIfNeeded()
946
+ }
947
+
948
+ private fun collectExecutionsResultFields () {
949
+ val successfulExecutionsModels = allExecutions
950
+ .filter {
951
+ it.result is UtExecutionSuccess
952
+ }.map {
953
+ (it.result as UtExecutionSuccess ).model
954
+ }
955
+
956
+ for (model in successfulExecutionsModels) {
957
+ when (model) {
958
+ is UtCompositeModel -> {
959
+ for ((fieldId, fieldModel) in model.fields) {
960
+ collectExecutionsResultFieldsRecursively(fieldId, fieldModel, 0 )
961
+ }
962
+ }
963
+
964
+ is UtAssembleModel -> {
965
+ model.origin?.let {
966
+ for ((fieldId, fieldModel) in it.fields) {
967
+ collectExecutionsResultFieldsRecursively(fieldId, fieldModel, 0 )
968
+ }
969
+ }
970
+ }
971
+
972
+ is UtNullModel ,
973
+ is UtPrimitiveModel ,
974
+ is UtArrayModel ,
975
+ is UtClassRefModel ,
976
+ is UtEnumConstantModel ,
977
+ is UtVoidModel -> {
978
+ // only [UtCompositeModel] and [UtAssembleModel] have fields to traverse
979
+ }
980
+ }
981
+ }
982
+ }
983
+
984
+ private fun collectExecutionsResultFieldsRecursively (
985
+ fieldId : FieldId ,
986
+ fieldModel : UtModel ,
987
+ depth : Int ,
988
+ ) {
989
+ if (depth >= DEEP_EQUALS_MAX_DEPTH ) {
990
+ return
991
+ }
992
+
993
+ val fieldKey = fieldId to depth
994
+ fieldsOfExecutionResults.getOrPut(fieldKey) { mutableListOf () } + = fieldModel
995
+
996
+ when (fieldModel) {
997
+ is UtCompositeModel -> {
998
+ for ((id, model) in fieldModel.fields) {
999
+ collectExecutionsResultFieldsRecursively(id, model, depth + 1 )
1000
+ }
1001
+ }
1002
+
1003
+ is UtAssembleModel -> {
1004
+ fieldModel.origin?.let {
1005
+ for ((id, model) in it.fields) {
1006
+ collectExecutionsResultFieldsRecursively(id, model, depth + 1 )
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ is UtNullModel ,
1012
+ is UtPrimitiveModel ,
1013
+ is UtArrayModel ,
1014
+ is UtClassRefModel ,
1015
+ is UtEnumConstantModel ,
1016
+ is UtVoidModel -> {
1017
+ // only [UtCompositeModel] and [UtAssembleModel] have fields to traverse
1018
+ }
1019
+ }
1020
+ }
1021
+
869
1022
@Suppress(" UNUSED_ANONYMOUS_PARAMETER" )
870
1023
private fun createDeclarationForFieldFromVariable (
871
1024
fieldId : FieldId ,
@@ -999,7 +1152,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
999
1152
}
1000
1153
expected == nullLiteral() -> testFrameworkManager.assertNull(actual)
1001
1154
expected is CgLiteral && expected.value is Boolean -> {
1002
- when (parameterizedTestSource ) {
1155
+ when (parametrizedTestSource ) {
1003
1156
ParametrizedTestSource .DO_NOT_PARAMETRIZE ->
1004
1157
testFrameworkManager.assertBoolean(expected.value, actual)
1005
1158
ParametrizedTestSource .PARAMETRIZE ->
@@ -1054,15 +1207,19 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1054
1207
expected : CgValue ,
1055
1208
actual : CgVariable ,
1056
1209
) {
1057
- when (parameterizedTestSource ) {
1210
+ when (parametrizedTestSource ) {
1058
1211
ParametrizedTestSource .DO_NOT_PARAMETRIZE -> generateDeepEqualsAssertion(expected, actual)
1059
- ParametrizedTestSource .PARAMETRIZE -> when {
1060
- actual.type.isPrimitive -> generateDeepEqualsAssertion(expected, actual)
1061
- else -> ifStatement(
1062
- CgEqualTo (expected, nullLiteral()),
1063
- trueBranch = { + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement() },
1064
- falseBranch = { generateDeepEqualsAssertion(expected, actual) }
1065
- )
1212
+ ParametrizedTestSource .PARAMETRIZE -> {
1213
+ collectExecutionsResultFields()
1214
+
1215
+ when {
1216
+ actual.type.isPrimitive -> generateDeepEqualsAssertion(expected, actual)
1217
+ else -> ifStatement(
1218
+ CgEqualTo (expected, nullLiteral()),
1219
+ trueBranch = { + testFrameworkManager.assertions[testFramework.assertNull](actual).toStatement() },
1220
+ falseBranch = { generateDeepEqualsAssertion(expected, actual) }
1221
+ )
1222
+ }
1066
1223
}
1067
1224
}
1068
1225
}
0 commit comments