diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index 07f0be271b..565bb51a25 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -98,6 +98,22 @@ data class UtMethodTestSet( val clustersInfo: List> = listOf(null to executions.indices) ) +data class CgMethodTestSet private constructor( + val executableId: ExecutableId, + val executions: List = emptyList(), + val jimpleBody: JimpleBody? = null, + val errors: Map = emptyMap(), + val clustersInfo: List> = listOf(null to executions.indices) +) { + constructor(from: UtMethodTestSet) : this( + from.method.callable.executableId, + from.executions, + from.jimpleBody, + from.errors, + from.clustersInfo + ) +} + data class Step( val stmt: Stmt, val depth: Int, diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt index b760070557..cdeb6a0a87 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt @@ -46,6 +46,8 @@ import kotlin.reflect.jvm.javaMethod import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentHashMapOf import org.utbot.engine.pc.UtSolverStatusUNDEFINED +import org.utbot.framework.plugin.api.ExecutableId +import org.utbot.framework.plugin.api.util.executableId import soot.ArrayType import soot.PrimType import soot.RefLikeType @@ -326,15 +328,28 @@ val UtMethod.signature: String return "${methodName}()" } +val ExecutableId.displayName: String + get() { + val executableName = this.name + val parameters = this.parameters.joinToString(separator = ", ") { it.canonicalName } + return "$executableName($parameters)" + } + +val Constructor<*>.displayName: String + get() = executableId.displayName + +val Method.displayName: String + get() = executableId.displayName + val UtMethod.displayName: String get() { - val methodName = this.callable.name - val javaMethod = this.javaMethod ?: this.javaConstructor - if (javaMethod != null) { - val parameters = javaMethod.parameters.joinToString(separator = ", ") { "${it.type.canonicalName}" } - return "${methodName}($parameters)" + val executableId = this.javaMethod?.executableId ?: this.javaConstructor?.executableId + return if (executableId != null) { + executableId.displayName + } else { + val methodName = this.callable.name + return "${methodName}()" } - return "${methodName}()" } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/CodeGenerator.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/CodeGenerator.kt index 01a3199c7c..9904dc13bd 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/CodeGenerator.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/CodeGenerator.kt @@ -12,15 +12,16 @@ import org.utbot.framework.codegen.model.constructor.tree.CgTestClassConstructor import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport import org.utbot.framework.codegen.model.tree.CgTestClassFile import org.utbot.framework.codegen.model.visitor.CgAbstractRenderer +import org.utbot.framework.plugin.api.CgMethodTestSet import org.utbot.framework.plugin.api.CodegenLanguage +import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.MockFramework -import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.UtMethodTestSet import org.utbot.framework.plugin.api.util.id class CodeGenerator( private val classUnderTest: Class<*>, - params: MutableMap, List> = mutableMapOf(), + paramNames: MutableMap> = mutableMapOf(), testFramework: TestFramework = TestFramework.defaultItem, mockFramework: MockFramework? = MockFramework.defaultItem, staticsMocking: StaticsMocking = StaticsMocking.defaultItem, @@ -35,7 +36,7 @@ class CodeGenerator( ) { private var context: CgContext = CgContext( classUnderTest = classUnderTest.id, - paramNames = params, + paramNames = paramNames, testFramework = testFramework, mockFramework = mockFramework ?: MockFramework.MOCKITO, codegenLanguage = codegenLanguage, @@ -57,13 +58,20 @@ class CodeGenerator( fun generateAsStringWithTestReport( testSets: Collection, testClassCustomName: String? = null, - ): TestsCodeWithTestReport = - withCustomContext(testClassCustomName) { - context.withClassScope { - val testClassFile = CgTestClassConstructor(context).construct(testSets) - TestsCodeWithTestReport(renderClassFile(testClassFile), testClassFile.testsGenerationReport) - } - } + ): TestsCodeWithTestReport { + val cgTestSets = testSets.map { CgMethodTestSet(it) }.toList() + return generateAsStringWithTestReport(cgTestSets, testClassCustomName) + } + + fun generateAsStringWithTestReport( + cgTestSets: List, + testClassCustomName: String? = null, + ): TestsCodeWithTestReport = withCustomContext(testClassCustomName) { + context.withClassScope { + val testClassFile = CgTestClassConstructor(context).construct(cgTestSets) + TestsCodeWithTestReport(renderClassFile(testClassFile), testClassFile.testsGenerationReport) + } + } /** * Wrapper function that configures context as needed for utbot-online: diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt index c271cce902..bfd2d49d15 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt @@ -42,10 +42,8 @@ import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.MethodId import org.utbot.framework.plugin.api.MockFramework import org.utbot.framework.plugin.api.UtExecution -import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtReferenceModel -import org.utbot.framework.plugin.api.UtMethodTestSet import java.util.IdentityHashMap import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.PersistentMap @@ -55,7 +53,7 @@ import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentSetOf import org.utbot.framework.codegen.model.constructor.builtin.streamsDeepEqualsMethodId import org.utbot.framework.codegen.model.tree.CgParameterKind -import org.utbot.framework.plugin.api.util.executableId +import org.utbot.framework.plugin.api.CgMethodTestSet import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.isCheckedException import org.utbot.framework.plugin.api.util.isSubtypeOf @@ -121,7 +119,7 @@ internal interface CgContextOwner { val prevStaticFieldValues: MutableMap // names of parameters of methods under test - val paramNames: Map, List> + val paramNames: Map> // UtExecution we currently generate a test method for. // It is null when no test method is being generated at the moment. @@ -176,7 +174,7 @@ internal interface CgContextOwner { // map from a set of tests for a method to another map // which connects code generation error message // with the number of times it occurred - val codeGenerationErrors: MutableMap> + val codeGenerationErrors: MutableMap> // package for generated test class val testClassPackageName: String @@ -233,8 +231,8 @@ internal interface CgContextOwner { currentBlock = currentBlock.add(it) } - fun updateCurrentExecutable(method: UtMethod<*>) { - currentExecutable = method.callable.executableId + fun updateCurrentExecutable(executableId: ExecutableId) { + currentExecutable = executableId } fun addExceptionIfNeeded(exception: ClassId) { @@ -399,7 +397,7 @@ internal data class CgContext( override val testMethods: MutableList = mutableListOf(), override val existingMethodNames: MutableSet = mutableSetOf(), override val prevStaticFieldValues: MutableMap = mutableMapOf(), - override val paramNames: Map, List>, + override val paramNames: Map>, override var currentExecution: UtExecution? = null, override val testFramework: TestFramework, override val mockFramework: MockFramework, @@ -415,7 +413,7 @@ internal data class CgContext( override var declaredExecutableRefs: PersistentMap = persistentMapOf(), override var thisInstance: CgValue? = null, override val methodArguments: MutableList = mutableListOf(), - override val codeGenerationErrors: MutableMap> = mutableMapOf(), + override val codeGenerationErrors: MutableMap> = mutableMapOf(), override val testClassPackageName: String = classUnderTest.packageName, override var shouldOptimizeImports: Boolean = false, override var testClassCustomName: String? = null, 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 aabaae88ff..44d7e226f0 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 @@ -7,9 +7,8 @@ import org.utbot.framework.codegen.model.constructor.util.infiniteInts import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.ConstructorId +import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.MethodId -import org.utbot.framework.plugin.api.UtMethod -import org.utbot.framework.plugin.api.util.executableId import org.utbot.framework.plugin.api.util.isArray /** @@ -45,7 +44,7 @@ internal interface CgNameGenerator { /** * Generate a new test method name. */ - fun testMethodNameFor(method: UtMethod<*>, customName: String? = null): String + fun testMethodNameFor(executableId: ExecutableId, customName: String? = null): String /** * Generates a new parameterized test method name by data provider method name. @@ -55,12 +54,12 @@ internal interface CgNameGenerator { /** * Generates a new data for parameterized test provider method name */ - fun dataProviderMethodNameFor(method: UtMethod<*>): String + fun dataProviderMethodNameFor(executableId: ExecutableId): String /** * Generate a new error method name */ - fun errorMethodNameFor(method: UtMethod<*>): String + fun errorMethodNameFor(executableId: ExecutableId): String } /** @@ -86,10 +85,10 @@ internal class CgNameGeneratorImpl(private val context: CgContext) return variableName(baseName.decapitalize(), isMock) } - override fun testMethodNameFor(method: UtMethod<*>, customName: String?): String { - val executableName = when (val id = method.callable.executableId) { - is ConstructorId -> id.classId.prettifiedName // TODO: maybe we need some suffix e.g. "Ctor"? - is MethodId -> id.name + 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 } // no index suffix allowed only when there's a vacant custom name val name = if (customName != null && customName !in existingMethodNames) { @@ -107,17 +106,17 @@ internal class CgNameGeneratorImpl(private val context: CgContext) override fun parameterizedTestMethodName(dataProviderMethodName: String) = dataProviderMethodName.replace(dataProviderMethodPrefix, "parameterizedTestsFor") - override fun dataProviderMethodNameFor(method: UtMethod<*>): String { - val indexedName = nextIndexedMethodName(method.callable.name.capitalize(), skipOne = true) + override fun dataProviderMethodNameFor(executableId: ExecutableId): String { + val indexedName = nextIndexedMethodName(executableId.name.capitalize(), skipOne = true) existingMethodNames += indexedName return "$dataProviderMethodPrefix$indexedName" } - override fun errorMethodNameFor(method: UtMethod<*>): String { - val executableName = when (val id = method.callable.executableId) { - is ConstructorId -> id.classId.prettifiedName - is MethodId -> id.name + override fun errorMethodNameFor(executableId: ExecutableId): String { + val executableName = when (executableId) { + is ConstructorId -> executableId.classId.prettifiedName + is MethodId -> executableId.name } val newName = when (val base = "test${executableName.capitalize()}_errors") { !in existingMethodNames -> base 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 165134a0c5..3c1f25fe80 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 @@ -2,7 +2,6 @@ package org.utbot.framework.codegen.model.constructor.tree import org.utbot.common.PathUtil import org.utbot.common.packageName -import org.utbot.engine.isStatic import org.utbot.framework.assemble.assemble import org.utbot.framework.codegen.ForceStaticMocking import org.utbot.framework.codegen.Junit4 @@ -86,6 +85,7 @@ import org.utbot.framework.fields.ExecutionStateAnalyzer import org.utbot.framework.fields.FieldPath import org.utbot.framework.plugin.api.BuiltinClassId import org.utbot.framework.plugin.api.BuiltinMethodId +import org.utbot.framework.plugin.api.CgMethodTestSet import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.ConcreteExecutionFailureException @@ -106,8 +106,6 @@ import org.utbot.framework.plugin.api.UtExecution import org.utbot.framework.plugin.api.UtExecutionFailure import org.utbot.framework.plugin.api.UtExecutionSuccess import org.utbot.framework.plugin.api.UtExplicitlyThrownException -import org.utbot.framework.plugin.api.UtMethod -import org.utbot.framework.plugin.api.UtMethodTestSet import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtNewInstanceInstrumentation import org.utbot.framework.plugin.api.UtNullModel @@ -123,6 +121,7 @@ import org.utbot.framework.plugin.api.util.builtinStaticMethodId import org.utbot.framework.plugin.api.util.doubleArrayClassId import org.utbot.framework.plugin.api.util.doubleClassId import org.utbot.framework.plugin.api.util.doubleWrapperClassId +import org.utbot.framework.plugin.api.util.executable import org.utbot.framework.plugin.api.util.field import org.utbot.framework.plugin.api.util.floatArrayClassId import org.utbot.framework.plugin.api.util.floatClassId @@ -149,7 +148,6 @@ import org.utbot.framework.util.isUnit import org.utbot.summary.SummarySentenceConstants.TAB import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl import java.lang.reflect.InvocationTargetException -import kotlin.reflect.jvm.javaType private const val DEEP_EQUALS_MAX_DEPTH = 5 // TODO move it to plugin settings? @@ -1086,11 +1084,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } } - fun createTestMethod(utMethod: UtMethod<*>, execution: UtExecution): CgTestMethod = + fun createTestMethod(executableId: ExecutableId, execution: UtExecution): CgTestMethod = withTestMethodScope(execution) { - val testMethodName = nameGenerator.testMethodNameFor(utMethod, execution.testMethodName) + val testMethodName = nameGenerator.testMethodNameFor(executableId, execution.testMethodName) // TODO: remove this line when SAT-1273 is completed - execution.displayName = execution.displayName?.let { "${utMethod.callable.name}: $it" } + execution.displayName = execution.displayName?.let { "${executableId.name}: $it" } testMethod(testMethodName, execution.displayName) { rememberInitialStaticFields() val stateAnalyzer = ExecutionStateAnalyzer(execution) @@ -1105,7 +1103,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } // build arguments for ((index, param) in execution.stateBefore.parameters.withIndex()) { - val name = paramNames[utMethod]?.get(index) + val name = paramNames[executableId]?.get(index) methodArguments += variableConstructor.getOrCreateVariable(param, name) } rememberInitialEnvironmentState(modificationInfo) @@ -1165,7 +1163,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c private val expectedResultVarName = "expectedResult" private val expectedErrorVarName = "expectedError" - fun createParameterizedTestMethod(testSet: UtMethodTestSet, dataProviderMethodName: String): CgTestMethod { + fun createParameterizedTestMethod(testSet: CgMethodTestSet, dataProviderMethodName: String): CgTestMethod { //TODO: orientation on generic execution may be misleading, but what is the alternative? //may be a heuristic to select a model with minimal number of internal nulls should be used val genericExecution = testSet.executions @@ -1217,11 +1215,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } private fun createParameterDeclarations( - testSet: UtMethodTestSet, + testSet: CgMethodTestSet, genericExecution: UtExecution, ): List { - val methodUnderTest = testSet.method - val methodUnderTestParameters = testSet.method.callable.parameters + val executableUnderTest = testSet.executableId + val executableUnderTestParameters = testSet.executableId.executable.parameters return mutableListOf().apply { // this instance @@ -1240,9 +1238,8 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } // arguments for (index in genericExecution.stateBefore.parameters.indices) { - val argumentName = paramNames[methodUnderTest]?.get(index) - val paramIndex = if (methodUnderTest.isStatic) index else index + 1 - val paramType = methodUnderTestParameters[paramIndex].type.javaType + val argumentName = paramNames[executableUnderTest]?.get(index) + val paramType = executableUnderTestParameters[index].parameterizedType val argumentType = when { paramType is Class<*> && paramType.isArray -> paramType.id @@ -1310,7 +1307,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c * Standard logic for generating each test case parameter code is used. */ fun createParameterizedTestDataProvider( - testSet: UtMethodTestSet, + testSet: CgMethodTestSet, dataProviderMethodName: String ): CgParameterizedTestDataProviderMethod { return withDataProviderScope { @@ -1335,14 +1332,14 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } } - private fun createExecutionArguments(testSet: UtMethodTestSet, execution: UtExecution): List { + private fun createExecutionArguments(testSet: CgMethodTestSet, execution: UtExecution): List { val arguments = mutableListOf() execution.stateBefore.thisInstance?.let { arguments += variableConstructor.getOrCreateVariable(it) } for ((paramIndex, paramModel) in execution.stateBefore.parameters.withIndex()) { - val argumentName = paramNames[testSet.method]?.get(paramIndex) + val argumentName = paramNames[testSet.executableId]?.get(paramIndex) arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName) } @@ -1567,7 +1564,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c arguments = arrayOf(objectArrayClassId) ) - private fun containsFailureExecution(testSet: UtMethodTestSet) = + private fun containsFailureExecution(testSet: CgMethodTestSet) = testSet.executions.any { it.result is UtExecutionFailure } @@ -1668,8 +1665,8 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } } - fun errorMethod(method: UtMethod<*>, errors: Map): CgRegion { - val name = nameGenerator.errorMethodNameFor(method) + fun errorMethod(executable: ExecutableId, errors: Map): CgRegion { + val name = nameGenerator.errorMethodNameFor(executable) val body = block { comment("Couldn't generate some tests. List of errors:") comment() @@ -1697,7 +1694,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c } } val errorTestMethod = CgErrorTestMethod(name, body) - return CgSimpleRegion("Errors report for ${method.callable.name}", listOf(errorTestMethod)) + return CgSimpleRegion("Errors report for ${executable.name}", listOf(errorTestMethod)) } private fun getJvmReportDocumentation(jvmReportPath: String): String { diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt index b3bb20dc6a..4d2c5c9b2a 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt @@ -23,10 +23,12 @@ import org.utbot.framework.codegen.model.tree.buildTestClass import org.utbot.framework.codegen.model.tree.buildTestClassBody import org.utbot.framework.codegen.model.tree.buildTestClassFile import org.utbot.framework.codegen.model.visitor.importUtilMethodDependencies +import org.utbot.framework.plugin.api.CgMethodTestSet +import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.MethodId -import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.UtMethodTestSet import org.utbot.framework.plugin.api.util.description +import org.utbot.framework.plugin.api.util.kClass import kotlin.reflect.KClass internal class CgTestClassConstructor(val context: CgContext) : @@ -43,7 +45,7 @@ internal class CgTestClassConstructor(val context: CgContext) : /** * Given a list of test sets constructs CgTestClass */ - fun construct(testSets: Collection): CgTestClassFile { + fun construct(testSets: Collection): CgTestClassFile { return buildTestClassFile { testClass = buildTestClass { // TODO: obtain test class from plugin @@ -51,7 +53,7 @@ internal class CgTestClassConstructor(val context: CgContext) : body = buildTestClassBody { cgDataProviderMethods.clear() for (testSet in testSets) { - updateCurrentExecutable(testSet.method) + updateCurrentExecutable(testSet.executableId) val currentMethodUnderTestRegions = construct(testSet) ?: continue val executableUnderTestCluster = CgExecutableUnderTestCluster( "Test suites for executable $currentExecutable", @@ -76,7 +78,7 @@ internal class CgTestClassConstructor(val context: CgContext) : } } - private fun construct(testSet: UtMethodTestSet): List>? { + private fun construct(testSet: CgMethodTestSet): List>? { if (testSet.executions.isEmpty()) { return null } @@ -106,7 +108,7 @@ internal class CgTestClassConstructor(val context: CgContext) : } ParametrizedTestSource.PARAMETRIZE -> { runCatching { - val dataProviderMethodName = nameGenerator.dataProviderMethodNameFor(testSet.method) + val dataProviderMethodName = nameGenerator.dataProviderMethodNameFor(testSet.executableId) val parameterizedTestMethod = methodConstructor.createParameterizedTestMethod(testSet, dataProviderMethodName) @@ -126,14 +128,14 @@ internal class CgTestClassConstructor(val context: CgContext) : val errors = testSet.allErrors if (errors.isNotEmpty()) { - regions += methodConstructor.errorMethod(testSet.method, errors) + regions += methodConstructor.errorMethod(testSet.executableId, errors) testsGenerationReport.addMethodErrors(testSet, errors) } return regions } - private fun processFailure(testSet: UtMethodTestSet, failure: Throwable) { + private fun processFailure(testSet: CgMethodTestSet, failure: Throwable) { codeGenerationErrors .getOrPut(testSet) { mutableMapOf() } .merge(failure.description, 1, Int::plus) @@ -172,23 +174,23 @@ internal class CgTestClassConstructor(val context: CgContext) : /** * Engine errors + codegen errors for a given [UtMethodTestSet] */ - private val UtMethodTestSet.allErrors: Map + private val CgMethodTestSet.allErrors: Map get() = errors + codeGenerationErrors.getOrDefault(this, mapOf()) } -typealias MethodGeneratedTests = MutableMap, MutableSet> +typealias MethodGeneratedTests = MutableMap> typealias ErrorsCount = Map data class TestsGenerationReport( - val executables: MutableSet> = mutableSetOf(), + val executables: MutableSet = mutableSetOf(), var successfulExecutions: MethodGeneratedTests = mutableMapOf(), var timeoutExecutions: MethodGeneratedTests = mutableMapOf(), var failedExecutions: MethodGeneratedTests = mutableMapOf(), var crashExecutions: MethodGeneratedTests = mutableMapOf(), - var errors: MutableMap, ErrorsCount> = mutableMapOf() + var errors: MutableMap = mutableMapOf() ) { val classUnderTest: KClass<*> - get() = executables.firstOrNull()?.clazz + get() = executables.firstOrNull()?.classId?.kClass ?: error("No executables found in test report") val initialWarnings: MutableList<() -> String> = mutableListOf() @@ -215,12 +217,12 @@ data class TestsGenerationReport( appendHtmlLine("Not generated because of internal errors test methods: $overallErrors") } - fun addMethodErrors(testSet: UtMethodTestSet, errors: Map) { - this.errors[testSet.method] = errors + fun addMethodErrors(testSet: CgMethodTestSet, errors: Map) { + this.errors[testSet.executableId] = errors } - fun addTestsByType(testSet: UtMethodTestSet, testMethods: List) { - with(testSet.method) { + fun addTestsByType(testSet: CgMethodTestSet, testMethods: List) { + with(testSet.executableId) { executables += this testMethods.forEach { @@ -257,19 +259,19 @@ data class TestsGenerationReport( override fun toString(): String = toString(false) - private fun UtMethod<*>.countTestMethods(): TestMethodStatistic = TestMethodStatistic( + private fun ExecutableId.countTestMethods(): TestMethodStatistic = TestMethodStatistic( testMethodsNumber(successfulExecutions), testMethodsNumber(failedExecutions), testMethodsNumber(timeoutExecutions), testMethodsNumber(crashExecutions) ) - private fun UtMethod<*>.countErrors(): Int = errors.getOrDefault(this, emptyMap()).values.sum() + private fun ExecutableId.countErrors(): Int = errors.getOrDefault(this, emptyMap()).values.sum() - private fun UtMethod<*>.testMethodsNumber(executables: MethodGeneratedTests): Int = + private fun ExecutableId.testMethodsNumber(executables: MethodGeneratedTests): Int = executables.getOrDefault(this, emptySet()).size - private fun UtMethod<*>.updateExecutions(it: CgTestMethod, executions: MethodGeneratedTests) { + private fun ExecutableId.updateExecutions(it: CgTestMethod, executions: MethodGeneratedTests) { executions.getOrPut(this) { mutableSetOf() } += it } diff --git a/utbot-framework/src/test/kotlin/org/utbot/framework/codegen/TestCodeGeneratorPipeline.kt b/utbot-framework/src/test/kotlin/org/utbot/framework/codegen/TestCodeGeneratorPipeline.kt index 95af9e2a8d..213da4803d 100644 --- a/utbot-framework/src/test/kotlin/org/utbot/framework/codegen/TestCodeGeneratorPipeline.kt +++ b/utbot-framework/src/test/kotlin/org/utbot/framework/codegen/TestCodeGeneratorPipeline.kt @@ -7,13 +7,12 @@ import org.utbot.common.bracket import org.utbot.common.info import org.utbot.common.packageName import org.utbot.examples.TestFrameworkConfiguration -import org.utbot.examples.conflictTriggers import org.utbot.framework.codegen.ExecutionStatus.SUCCESS import org.utbot.framework.codegen.model.CodeGenerator import org.utbot.framework.plugin.api.CodegenLanguage +import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.MockFramework import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.UtMethodTestSet import org.utbot.framework.plugin.api.util.UtContext import org.utbot.framework.plugin.api.util.description @@ -217,12 +216,12 @@ class TestCodeGeneratorPipeline(private val testFrameworkConfiguration: TestFram testSets: List, classUnderTest: KClass<*> ): String { - val params = mutableMapOf, List>() + val params = mutableMapOf>() val codeGenerator = with(testFrameworkConfiguration) { CodeGenerator( classUnderTest.java, - params = params, + paramNames = params, testFramework = testFramework, staticsMocking = staticsMocking, forceStaticMocking = forceStaticMocking, diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt index af33856772..e53d7fb37f 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt @@ -55,9 +55,10 @@ import org.utbot.framework.codegen.model.CodeGenerator import org.utbot.framework.codegen.model.TestsCodeWithTestReport import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport import org.utbot.framework.plugin.api.CodegenLanguage -import org.utbot.framework.plugin.api.UtMethod +import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.UtMethodTestSet import org.utbot.framework.plugin.api.util.UtContext +import org.utbot.framework.plugin.api.util.executableId import org.utbot.framework.plugin.api.util.withUtContext import org.utbot.framework.util.Conflict import org.utbot.intellij.plugin.generator.CodeGenerationController.Target.* @@ -100,7 +101,7 @@ object CodeGenerationController { val file = testClass.containingFile runWriteCommandAction(model.project, "Generate tests with UtBot", null, { try { - generateCodeAndReport(testClass, file, testSets, model, latch, reports) + generateCodeAndReport(srcClass, testClass, file, testSets, model, latch, reports) } catch (e: IncorrectOperationException) { showCreatingClassError(model.project, createTestClassName(srcClass)) } @@ -250,6 +251,7 @@ object CodeGenerationController { } private fun generateCodeAndReport( + srcClass: PsiClass, testClass: PsiClass, file: PsiFile, testSets: List, @@ -257,24 +259,19 @@ object CodeGenerationController { reportsCountDown: CountDownLatch, reports: MutableList, ) { - val selectedMethods = TestIntegrationUtils.extractClassMethods(testClass, false) - val testFramework = model.testFramework - val mockito = model.mockFramework - val staticsMocking = model.staticsMocking - val classUnderTest = testSets.first().method.clazz - - val params = DumbService.getInstance(model.project) - .runReadActionInSmartMode(Computable { findMethodParams(classUnderTest, selectedMethods) }) + val classMethods = TestIntegrationUtils.extractClassMethods(srcClass, false) + val paramNames = DumbService.getInstance(model.project) + .runReadActionInSmartMode(Computable { findMethodParamNames(classUnderTest, classMethods) }) val codeGenerator = CodeGenerator( classUnderTest = classUnderTest.java, - params = params.toMutableMap(), - testFramework = testFramework, - mockFramework = mockito, + paramNames = paramNames.toMutableMap(), + testFramework = model.testFramework, + mockFramework = model.mockFramework, codegenLanguage = model.codegenLanguage, parameterizedTestSource = model.parametrizedTestSource, - staticsMocking = staticsMocking, + staticsMocking = model.staticsMocking, forceStaticMocking = model.forceStaticMocking, generateWarningsForStaticMocking = model.generateWarningsForStaticMocking, runtimeExceptionTestsBehaviour = model.runtimeExceptionTestsBehaviour, @@ -347,13 +344,11 @@ object CodeGenerationController { } } - private fun findMethodParams(clazz: KClass<*>, methods: List): Map, List> { + private fun findMethodParamNames(clazz: KClass<*>, methods: List): Map> { val bySignature = methods.associate { it.signature() to it.paramNames() } - return clazz.functions.mapNotNull { method -> - bySignature[method.signature()]?.let { params -> - UtMethod(method, clazz) to params - } - }.toMap() + return clazz.functions + .mapNotNull { method -> bySignature[method.signature()]?.let { params -> method.executableId to params } } + .toMap() } private fun MemberInfo.paramNames(): List =