@@ -216,8 +216,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
216
216
* Thus, this method only caches an actual initial static fields state in order to recover it
217
217
* at the end of the test, and it has nothing to do with the 'before' and 'after' caches.
218
218
*/
219
- private fun rememberInitialStaticFields () {
220
- for ((field, _) in currentExecution!! .stateBefore.statics.accessibleFields()) {
219
+ private fun rememberInitialStaticFields (statics : Map <FieldId , UtModel >) {
220
+ val accessibleStaticFields = statics.accessibleFields()
221
+ for ((field, _) in accessibleStaticFields) {
221
222
val declaringClass = field.declaringClass
222
223
val fieldAccessible = field.isAccessibleFrom(testClassPackageName)
223
224
@@ -240,11 +241,18 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
240
241
}
241
242
}
242
243
243
- private fun mockStaticFields () {
244
- for ((field, model) in currentExecution!! .stateBefore.statics.accessibleFields()) {
244
+ private fun substituteStaticFields (statics : Map <FieldId , UtModel >, isParametrized : Boolean = false) {
245
+ val accessibleStaticFields = statics.accessibleFields()
246
+ for ((field, model) in accessibleStaticFields) {
245
247
val declaringClass = field.declaringClass
246
248
val fieldAccessible = field.canBeSetIn(testClassPackageName)
247
- val fieldValue = variableConstructor.getOrCreateVariable(model, field.name)
249
+
250
+ val fieldValue = if (isParametrized) {
251
+ currentMethodParameters[CgParameterKind .Statics (model)]
252
+ } else {
253
+ variableConstructor.getOrCreateVariable(model, field.name)
254
+ }
255
+
248
256
if (fieldAccessible) {
249
257
declaringClass[field] `= ` fieldValue
250
258
} else {
@@ -1100,12 +1108,13 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1100
1108
// TODO: remove this line when SAT-1273 is completed
1101
1109
execution.displayName = execution.displayName?.let { " ${utMethod.callable.name} : $it " }
1102
1110
testMethod(testMethodName, execution.displayName) {
1103
- rememberInitialStaticFields()
1111
+ val statics = currentExecution!! .stateBefore.statics
1112
+ rememberInitialStaticFields(statics)
1104
1113
val stateAnalyzer = ExecutionStateAnalyzer (execution)
1105
1114
val modificationInfo = stateAnalyzer.findModifiedFields()
1106
1115
// TODO: move such methods to another class and leave only 2 public methods: remember initial and final states
1107
1116
val mainBody = {
1108
- mockStaticFields( )
1117
+ substituteStaticFields(statics )
1109
1118
setupInstrumentation()
1110
1119
// build this instance
1111
1120
thisInstance = execution.stateBefore.thisInstance?.let {
@@ -1123,7 +1132,6 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1123
1132
generateFieldStateAssertions()
1124
1133
}
1125
1134
1126
- val statics = currentExecution!! .stateBefore.statics
1127
1135
if (statics.isNotEmpty()) {
1128
1136
+ tryBlock {
1129
1137
mainBody()
@@ -1180,11 +1188,14 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1180
1188
.firstOrNull { it.result is UtExecutionSuccess && (it.result as UtExecutionSuccess ).model !is UtNullModel }
1181
1189
? : testSet.executions.first()
1182
1190
1191
+ val statics = genericExecution.stateBefore.statics
1192
+
1183
1193
return withTestMethodScope(genericExecution) {
1184
1194
val testName = nameGenerator.parameterizedTestMethodName(dataProviderMethodName)
1185
1195
withNameScope {
1186
1196
val testParameterDeclarations = createParameterDeclarations(testSet, genericExecution)
1187
1197
val mainBody = {
1198
+ substituteStaticFields(statics, isParametrized = true )
1188
1199
// build this instance
1189
1200
thisInstance = genericExecution.stateBefore.thisInstance?.let { currentMethodParameters[CgParameterKind .ThisInstance ] }
1190
1201
@@ -1206,16 +1217,30 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1206
1217
parameterized = true ,
1207
1218
dataProviderMethodName
1208
1219
) {
1209
- if (containsFailureExecution(testSet)) {
1210
- + tryBlock(mainBody)
1211
- .catch (Throwable ::class .java.id) { e ->
1220
+ rememberInitialStaticFields(statics)
1221
+
1222
+ if (containsFailureExecution(testSet) || statics.isNotEmpty()) {
1223
+ var currentTryBlock = tryBlock {
1224
+ mainBody()
1225
+ }
1226
+
1227
+ if (containsFailureExecution(testSet)) {
1228
+ currentTryBlock = currentTryBlock.catch (Throwable ::class .java.id) { e ->
1212
1229
val pseudoExceptionVarName = when (codegenLanguage) {
1213
1230
CodegenLanguage .JAVA -> " ${expectedErrorVarName} .isInstance(${e.name.decapitalize()} )"
1214
1231
CodegenLanguage .KOTLIN -> " ${expectedErrorVarName} !!.isInstance(${e.name.decapitalize()} )"
1215
1232
}
1216
1233
1217
1234
testFrameworkManager.assertBoolean(CgVariable (pseudoExceptionVarName, booleanClassId))
1218
1235
}
1236
+ }
1237
+
1238
+ if (statics.isNotEmpty()) {
1239
+ currentTryBlock = currentTryBlock.finally {
1240
+ recoverStaticFields()
1241
+ }
1242
+ }
1243
+ + currentTryBlock
1219
1244
} else {
1220
1245
mainBody()
1221
1246
}
@@ -1269,6 +1294,22 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1269
1294
currentMethodParameters[CgParameterKind .Argument (index)] = argument.parameter
1270
1295
}
1271
1296
1297
+ val statics = genericExecution.stateBefore.statics
1298
+ if (statics.isNotEmpty()) {
1299
+ for ((fieldId, model) in statics) {
1300
+ val staticType = wrapTypeIfRequired(model.classId)
1301
+ val static = CgParameterDeclaration (
1302
+ parameter = declareParameter(
1303
+ type = staticType,
1304
+ name = nameGenerator.variableName(fieldId.name, isStatic = true )
1305
+ ),
1306
+ isReferenceType = staticType.isRefType
1307
+ )
1308
+ this + = static
1309
+ currentMethodParameters[CgParameterKind .Statics (model)] = static.parameter
1310
+ }
1311
+ }
1312
+
1272
1313
val expectedResultClassId = wrapTypeIfRequired(testSet.resultType())
1273
1314
if (expectedResultClassId != voidClassId) {
1274
1315
val wrappedType = wrapIfPrimitive(expectedResultClassId)
@@ -1351,6 +1392,12 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
1351
1392
arguments + = variableConstructor.getOrCreateVariable(paramModel, argumentName)
1352
1393
}
1353
1394
1395
+ val statics = execution.stateBefore.statics
1396
+ for ((field, model) in statics) {
1397
+ arguments + = variableConstructor.getOrCreateVariable(model, field.name)
1398
+ }
1399
+
1400
+
1354
1401
val method = currentExecutable!!
1355
1402
val needsReturnValue = method.returnType != voidClassId
1356
1403
val containsFailureExecution = containsFailureExecution(testSet)
0 commit comments