From dbf02bc549e7ce093a0377fcdb4fc1befec3bfc7 Mon Sep 17 00:00:00 2001 From: Andrey Tarbeev Date: Mon, 1 Aug 2022 18:23:01 +0300 Subject: [PATCH] Add constructorId support in parametrized test generation & refactor name generator --- .../model/constructor/name/CgNameGenerator.kt | 21 +++-- .../constructor/tree/CgMethodConstructor.kt | 89 ++++++++++--------- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/name/CgNameGenerator.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/name/CgNameGenerator.kt index 44d7e226f0..3fd130deec 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/name/CgNameGenerator.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/name/CgNameGenerator.kt @@ -86,10 +86,8 @@ internal class CgNameGeneratorImpl(private val context: CgContext) } override fun testMethodNameFor(executableId: ExecutableId, customName: String?): String { - val executableName = when (executableId) { - is ConstructorId -> executableId.classId.prettifiedName // TODO: maybe we need some suffix e.g. "Ctor"? - is MethodId -> executableId.name - } + val executableName = createExecutableName(executableId) + // no index suffix allowed only when there's a vacant custom name val name = if (customName != null && customName !in existingMethodNames) { customName @@ -107,17 +105,15 @@ internal class CgNameGeneratorImpl(private val context: CgContext) dataProviderMethodName.replace(dataProviderMethodPrefix, "parameterizedTestsFor") override fun dataProviderMethodNameFor(executableId: ExecutableId): String { - val indexedName = nextIndexedMethodName(executableId.name.capitalize(), skipOne = true) + val executableName = createExecutableName(executableId) + val indexedName = nextIndexedMethodName(executableName.capitalize(), skipOne = true) existingMethodNames += indexedName return "$dataProviderMethodPrefix$indexedName" } override fun errorMethodNameFor(executableId: ExecutableId): String { - val executableName = when (executableId) { - is ConstructorId -> executableId.classId.prettifiedName - is MethodId -> executableId.name - } + val executableName = createExecutableName(executableId) val newName = when (val base = "test${executableName.capitalize()}_errors") { !in existingMethodNames -> base else -> nextIndexedMethodName(base) @@ -151,6 +147,13 @@ internal class CgNameGeneratorImpl(private val context: CgContext) if (baseName !in existingVariableNames) "`$baseName`" else nextIndexedVarName(baseName) } } + + private fun createExecutableName(executableId: ExecutableId): String { + return when (executableId) { + is ConstructorId -> executableId.classId.prettifiedName // TODO: maybe we need some suffix e.g. "Ctor"? + is MethodId -> executableId.name + } + } } /** diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt index 3c1f25fe80..bd9fae8987 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt @@ -282,30 +282,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c */ private fun generateResultAssertions() { when (currentExecutable) { - is ConstructorId -> { - // we cannot generate any assertions for constructor testing - // but we need to generate a constructor call - val constructorCall = currentExecutable as ConstructorId - val currentExecution = currentExecution!! - currentExecution.result - .onSuccess { - methodType = SUCCESSFUL - - // TODO engine returns UtCompositeModel sometimes (concrete execution?) - - // TODO support inner classes constructors testing JIRA:1461 - require(!constructorCall.classId.isInner) { - "Inner class ${constructorCall.classId} constructor testing is not supported yet" - } - - actual = newVar(constructorCall.classId, "actual") { - constructorCall(*methodArguments.toTypedArray()) - } - } - .onFailure { exception -> - processExecutionFailure(currentExecution, exception) - } - } + is ConstructorId -> generateConstructorCall(currentExecutable!!, currentExecution!!) is BuiltinMethodId -> error("Unexpected BuiltinMethodId $currentExecutable while generating result assertions") is MethodId -> { emptyLineIfNeeded() @@ -430,24 +407,30 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c */ private fun generateAssertionsForParameterizedTest() { emptyLineIfNeeded() - val method = currentExecutable as MethodId - currentExecution!!.result - .onSuccess { result -> - if (result.isUnit()) { - +thisInstance[method](*methodArguments.toTypedArray()) - } else { - //"generic" expected variable is represented with a wrapper if - //actual result is primitive to support cases with exceptions. - resultModel = if (result is UtPrimitiveModel) assemble(result) else result - val expectedVariable = currentMethodParameters[CgParameterKind.ExpectedResult]!! - val expectedExpression = CgNotNullAssertion(expectedVariable) + when (currentExecutable) { + is ConstructorId -> generateConstructorCall(currentExecutable!!, currentExecution!!) + is MethodId -> { + val method = currentExecutable as MethodId + currentExecution!!.result + .onSuccess { result -> + if (result.isUnit()) { + +thisInstance[method](*methodArguments.toTypedArray()) + } else { + //"generic" expected variable is represented with a wrapper if + //actual result is primitive to support cases with exceptions. + resultModel = if (result is UtPrimitiveModel) assemble(result) else result - assertEquality(expectedExpression, actual) - println() - } + val expectedVariable = currentMethodParameters[CgParameterKind.ExpectedResult]!! + val expectedExpression = CgNotNullAssertion(expectedVariable) + + assertEquality(expectedExpression, actual) + println() + } + } + .onFailure { thisInstance[method](*methodArguments.toTypedArray()).intercepted() } } - .onFailure { thisInstance[method](*methodArguments.toTypedArray()).intercepted() } + } } /** @@ -1020,6 +1003,27 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c generateDeepEqualsOrNullAssertion(expected.expression, actual) } + private fun generateConstructorCall(currentExecutableId: ExecutableId, currentExecution: UtExecution) { + // we cannot generate any assertions for constructor testing + // but we need to generate a constructor call + val constructorCall = currentExecutableId as ConstructorId + currentExecution.result + .onSuccess { + methodType = SUCCESSFUL + + require(!constructorCall.classId.isInner) { + "Inner class ${constructorCall.classId} constructor testing is not supported yet" + } + + actual = newVar(constructorCall.classId, "actual") { + constructorCall(*methodArguments.toTypedArray()) + } + } + .onFailure { exception -> + processExecutionFailure(currentExecution, exception) + } + } + /** * We can't use standard deepEquals method in parametrized tests * because nullable objects require different asserts. @@ -1258,9 +1262,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c currentMethodParameters[CgParameterKind.Argument(index)] = argument.parameter } - val method = currentExecutable as MethodId - val containsFailureExecution = containsFailureExecution(testSet) - + val method = currentExecutable!! val expectedResultClassId = wrapTypeIfRequired(method.returnType) if (expectedResultClassId != voidClassId) { @@ -1278,6 +1280,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c currentMethodParameters[CgParameterKind.ExpectedResult] = expectedResult.parameter } + val containsFailureExecution = containsFailureExecution(testSet) if (containsFailureExecution) { val classClassId = Class::class.id val expectedException = CgParameterDeclaration( @@ -1343,7 +1346,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName) } - val method = currentExecutable as MethodId + val method = currentExecutable!! val needsReturnValue = method.returnType != voidClassId val containsFailureExecution = containsFailureExecution(testSet) execution.result