Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import org.utbot.framework.plugin.api.MockStrategyApi
import org.utbot.framework.plugin.api.TreatOverflowAsError
import org.utbot.framework.plugin.api.TestCaseGenerator
import org.utbot.framework.plugin.api.UtMethod
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import org.utbot.summary.summarize
import java.io.File
import java.lang.reflect.Method
Expand Down Expand Up @@ -158,7 +158,7 @@ abstract class GenerateTestsAbstractCommand(name: String, help: String) :
sourceCodeFile: Path? = null,
searchDirectory: Path,
chosenClassesToMockAlways: Set<ClassId>
): List<UtTestCase> =
): List<UtMethodTestSet> =
TestCaseGenerator.generate(
targetMethods,
mockStrategy,
Expand All @@ -184,11 +184,11 @@ abstract class GenerateTestsAbstractCommand(name: String, help: String) :
}
}

protected fun generateTest(classUnderTest: KClass<*>, testClassname: String, testCases: List<UtTestCase>): String =
protected fun generateTest(classUnderTest: KClass<*>, testClassname: String, testSets: List<UtMethodTestSet>): String =
initializeCodeGenerator(
testFramework,
classUnderTest
).generateAsString(testCases, testClassname)
).generateAsString(testSets, testClassname)

protected fun initializeEngine(workingDirectory: Path) {
val classPathNormalized =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.utbot.common.PathUtil.toPath
import org.utbot.engine.Mocker
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import org.utbot.framework.plugin.api.util.UtContext
import org.utbot.framework.plugin.api.util.withUtContext
import org.utbot.sarif.SarifReport
Expand Down Expand Up @@ -128,7 +128,7 @@ class GenerateTestsCommand :
}
}

private fun generateReport(classFqn: String, testCases: List<UtTestCase>, testClassBody: String) = try {
private fun generateReport(classFqn: String, testSets: List<UtMethodTestSet>, testClassBody: String) = try {
// reassignments for smart casts
val testsFilePath = output
val projectRootPath = projectRoot
Expand All @@ -143,7 +143,7 @@ class GenerateTestsCommand :
else -> {
val sourceFinding =
SourceFindingStrategyDefault(classFqn, sourceCodeFile, testsFilePath, projectRootPath)
val report = SarifReport(testCases, testClassBody, sourceFinding).createReport()
val report = SarifReport(testSets, testClassBody, sourceFinding).createReport()
saveToFile(report, sarifReport)
println("The report was saved to \"$sarifReport\". You can open it using the VS Code extension \"Sarif Viewer\".")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,13 @@ data class UtMethod<R>(
}
}

/**
* Test case.
*
* Note: it should not be transformed into data class since it is used as a key in maps.
* The clusters in it are mutable objects, therefore, we might have problems with hash because of it.
*/
@Suppress("unused")
class UtTestCase(
data class UtMethodTestSet(
val method: UtMethod<*>,
val executions: List<UtExecution> = emptyList(),
val jimpleBody: JimpleBody? = null,
val errors: Map<String, Int> = emptyMap(),
private val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
) {
operator fun component1() = method
operator fun component2() = executions
operator fun component3() = jimpleBody
operator fun component4() = errors
operator fun component5() = clustersInfo

fun copy(
method: UtMethod<*> = this.method,
executions: List<UtExecution> = this.executions,
jimpleBody: JimpleBody? = this.jimpleBody,
errors: Map<String, Int> = this.errors,
clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = this.clustersInfo
) = UtTestCase(method, executions, jimpleBody, errors, clustersInfo)
}
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
)

data class Step(
val stmt: Stmt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@

package org.utbot.framework.plugin.api

import kotlin.reflect.KClass
import org.apache.commons.lang3.builder.RecursiveToStringStyle
import org.apache.commons.lang3.builder.ReflectionToStringBuilder
import soot.jimple.JimpleBody

data class UtValueTestCase<R>(
data class UtMethodValueTestSet<R>(
val method: UtMethod<out R>,
val executions: List<UtValueExecution<out R>> = emptyList(),
val jimpleBody: JimpleBody? = null,
val errors: Map<String, Int> = emptyMap(),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import org.utbot.framework.plugin.api.TestCaseGenerator
import org.utbot.framework.plugin.api.UtExecution
import org.utbot.framework.plugin.api.UtMethod
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import org.utbot.framework.plugin.api.util.UtContext
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.isPrimitive
Expand Down Expand Up @@ -50,7 +50,7 @@ object UtBotJavaApi {
@JvmOverloads
fun generate(
methodsForGeneration: List<TestMethodInfo>,
generatedTestCases: List<UtTestCase> = mutableListOf(),
generatedTestCases: List<UtMethodTestSet> = mutableListOf(),
destinationClassName: String,
classpath: String,
dependencyClassPath: String,
Expand All @@ -66,15 +66,15 @@ object UtBotJavaApi {

val utContext = UtContext(classUnderTest.classLoader)

val testCases: MutableList<UtTestCase> = generatedTestCases.toMutableList()
val testSets: MutableList<UtMethodTestSet> = generatedTestCases.toMutableList()

val concreteExecutor = ConcreteExecutor(
UtExecutionInstrumentation,
classpath,
dependencyClassPath
)

testCases.addAll(generateUnitTests(concreteExecutor, methodsForGeneration, classUnderTest))
testSets.addAll(generateUnitTests(concreteExecutor, methodsForGeneration, classUnderTest))

if (stopConcreteExecutorOnExit) {
concreteExecutor.close()
Expand All @@ -95,7 +95,7 @@ object UtBotJavaApi {
}

testGenerator.generateAsString(
testCases,
testSets,
destinationClassName
)
}
Expand All @@ -115,12 +115,12 @@ object UtBotJavaApi {
dependencyClassPath: String,
mockStrategyApi: MockStrategyApi = MockStrategyApi.OTHER_PACKAGES,
generationTimeoutInMillis: Long = UtSettings.utBotGenerationTimeoutInMillis
): MutableList<UtTestCase> {
): MutableList<UtMethodTestSet> {

val utContext = UtContext(classUnderTest.classLoader)
val testCases: MutableList<UtTestCase> = mutableListOf()
val testSets: MutableList<UtMethodTestSet> = mutableListOf()

testCases.addAll(withUtContext(utContext) {
testSets.addAll(withUtContext(utContext) {
TestCaseGenerator
.apply {
init(
Expand All @@ -140,7 +140,7 @@ object UtBotJavaApi {
)
})

return testCases
return testSets
}

/**
Expand All @@ -158,7 +158,7 @@ object UtBotJavaApi {
mockStrategyApi: MockStrategyApi = MockStrategyApi.OTHER_PACKAGES,
generationTimeoutInMillis: Long = UtSettings.utBotGenerationTimeoutInMillis,
primitiveValuesSupplier: CustomFuzzerValueSupplier = CustomFuzzerValueSupplier { null }
): MutableList<UtTestCase> {
): MutableList<UtMethodTestSet> {
fun createPrimitiveModels(supplier: CustomFuzzerValueSupplier, classId: ClassId): Sequence<UtPrimitiveModel> =
supplier
.takeIf { classId.isPrimitive || classId.isPrimitiveWrapper || classId == stringClassId }
Expand Down Expand Up @@ -259,7 +259,7 @@ object UtBotJavaApi {

val utMethod = UtMethod(methodCallable, containingClass.kotlin)

UtTestCase(
UtMethodTestSet(
utMethod,
listOf(utExecution)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.utbot.framework.codegen.model.visitor.CgAbstractRenderer
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.MockFramework
import org.utbot.framework.plugin.api.UtMethod
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import org.utbot.framework.plugin.api.util.id

class CodeGenerator {
Expand Down Expand Up @@ -56,17 +56,17 @@ class CodeGenerator {
}

//TODO: we support custom test class name only in utbot-online, probably support them in plugin as well
fun generateAsString(testCases: Collection<UtTestCase>, testClassCustomName: String? = null): String =
generateAsStringWithTestReport(testCases, testClassCustomName).generatedCode
fun generateAsString(testSets: Collection<UtMethodTestSet>, testClassCustomName: String? = null): String =
generateAsStringWithTestReport(testSets, testClassCustomName).generatedCode

//TODO: we support custom test class name only in utbot-online, probably support them in plugin as well
fun generateAsStringWithTestReport(
testCases: Collection<UtTestCase>,
testSets: Collection<UtMethodTestSet>,
testClassCustomName: String? = null,
): TestsCodeWithTestReport =
withCustomContext(testClassCustomName) {
context.withClassScope {
val testClassFile = CgTestClassConstructor(context).construct(testCases)
val testClassFile = CgTestClassConstructor(context).construct(testSets)
TestsCodeWithTestReport(renderClassFile(testClassFile), testClassFile.testsGenerationReport)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ 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.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import java.util.IdentityHashMap
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.PersistentMap
Expand Down Expand Up @@ -178,7 +178,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<UtTestCase, MutableMap<String, Int>>
val codeGenerationErrors: MutableMap<UtMethodTestSet, MutableMap<String, Int>>

// package for generated test class
val testClassPackageName: String
Expand Down Expand Up @@ -418,7 +418,7 @@ internal data class CgContext(
override var declaredExecutableRefs: PersistentMap<ExecutableId, CgVariable> = persistentMapOf(),
override var thisInstance: CgValue? = null,
override val methodArguments: MutableList<CgValue> = mutableListOf(),
override val codeGenerationErrors: MutableMap<UtTestCase, MutableMap<String, Int>> = mutableMapOf(),
override val codeGenerationErrors: MutableMap<UtMethodTestSet, MutableMap<String, Int>> = mutableMapOf(),
override val testClassPackageName: String = classUnderTest.packageName,
override var shouldOptimizeImports: Boolean = false,
override var testClassCustomName: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ import org.utbot.framework.plugin.api.UtNullModel
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.UtReferenceModel
import org.utbot.framework.plugin.api.UtStaticMethodInstrumentation
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.UtMethodTestSet
import org.utbot.framework.plugin.api.UtTimeoutException
import org.utbot.framework.plugin.api.UtVoidModel
import org.utbot.framework.plugin.api.onFailure
Expand Down Expand Up @@ -1208,19 +1208,19 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
private val expectedResultVarName = "expectedResult"
private val expectedErrorVarName = "expectedError"

fun createParameterizedTestMethod(utTestCase: UtTestCase, dataProviderMethodName: String): CgTestMethod? {
val methodUnderTest = utTestCase.method
val methodUnderTestParameters = utTestCase.method.callable.parameters
fun createParameterizedTestMethod(testSet: UtMethodTestSet, dataProviderMethodName: String): CgTestMethod? {
val methodUnderTest = testSet.method
val methodUnderTestParameters = testSet.method.callable.parameters

if (utTestCase.executions.isEmpty()) {
if (testSet.executions.isEmpty()) {
return null
}

//TODO: orientation on arbitrary 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 arbitraryExecution = utTestCase.executions
val arbitraryExecution = testSet.executions
.firstOrNull { it.result is UtExecutionSuccess && (it.result as UtExecutionSuccess).model !is UtNullModel }
?: utTestCase.executions.first()
?: testSet.executions.first()

return withTestMethodScope(arbitraryExecution) {
val testName = nameGenerator.parameterizedTestMethodName(dataProviderMethodName)
Expand Down Expand Up @@ -1252,7 +1252,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
)
}
val method = currentExecutable as MethodId
val containsFailureExecution = containsFailureExecution(utTestCase)
val containsFailureExecution = containsFailureExecution(testSet)
if (method.returnType != voidClassId) {
testArguments += CgParameterDeclaration(
expectedResultVarName, resultClassId(method.returnType),
Expand Down Expand Up @@ -1280,7 +1280,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
parameterized = true,
dataProviderMethodName
) {
if (containsFailureExecution(utTestCase)) {
if (containsFailureExecution(testSet)) {
+tryBlock(mainBody)
.catch(Throwable::class.java.id) { e ->
val pseudoExceptionVarName = when (codegenLanguage) {
Expand Down Expand Up @@ -1312,20 +1312,20 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
* Standard logic for generating each test case parameter code is used.
*/
fun createParameterizedTestDataProvider(
utTestCase: UtTestCase,
testSet: UtMethodTestSet,
dataProviderMethodName: String
): CgParameterizedTestDataProviderMethod {
val dataProviderStatements = mutableListOf<CgStatement>()
val dataProviderExceptions = mutableSetOf<ClassId>()

val argListLength = utTestCase.executions.size
val argListLength = testSet.executions.size
val argListDeclaration = createArgList(argListLength)
val argListVariable = argListDeclaration.variable

dataProviderStatements += argListDeclaration
dataProviderStatements += CgEmptyLine()

for ((execIndex, execution) in utTestCase.executions.withIndex()) {
for ((execIndex, execution) in testSet.executions.withIndex()) {
withTestMethodScope(execution) {
//collect arguments
val arguments = mutableListOf<CgExpression>()
Expand All @@ -1335,13 +1335,13 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
}

for ((paramIndex, paramModel) in execution.stateBefore.parameters.withIndex()) {
val argumentName = paramNames[utTestCase.method]?.get(paramIndex)
val argumentName = paramNames[testSet.method]?.get(paramIndex)
arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName)
}

val method = currentExecutable as MethodId
val needsReturnValue = method.returnType != voidClassId
val containsFailureExecution = containsFailureExecution(utTestCase)
val containsFailureExecution = containsFailureExecution(testSet)
execution.result
.onSuccess {
if (needsReturnValue) {
Expand Down Expand Up @@ -1530,8 +1530,8 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
)
}

private fun containsFailureExecution(testCase: UtTestCase) =
testCase.executions.any { it.result is UtExecutionFailure }
private fun containsFailureExecution(testSet: UtMethodTestSet) =
testSet.executions.any { it.result is UtExecutionFailure }

private fun resultClassId(returnType: ClassId): ClassId = when (returnType) {
booleanClassId -> booleanWrapperClassId
Expand Down
Loading