Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added simple custom JavaDocs for the tests produced by Fuzzer #1069

Merged
merged 14 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

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 @@ -6,8 +6,8 @@ import com.intellij.psi.PsiReference
import com.intellij.psi.javadoc.CustomJavadocTagProvider
import com.intellij.psi.javadoc.JavadocTagInfo
import com.intellij.psi.javadoc.PsiDocTagValue
import org.utbot.summary.comment.CustomJavaDocTag
import org.utbot.summary.comment.CustomJavaDocTagProvider
import org.utbot.summary.comment.customtags.symbolic.CustomJavaDocTag
import org.utbot.summary.comment.customtags.symbolic.CustomJavaDocTagProvider

/**
* Provides plugin's custom JavaDoc tags to make test summaries structured.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import org.utbot.summary.UtSummarySettings.GENERATE_NAMES
import org.utbot.summary.analysis.ExecutionStructureAnalysis
import org.utbot.summary.ast.JimpleToASTMap
import org.utbot.summary.ast.SourceCodeParser
import org.utbot.summary.comment.SymbolicExecutionClusterCommentBuilder
import org.utbot.summary.comment.cluster.SymbolicExecutionClusterCommentBuilder
import org.utbot.summary.comment.SimpleCommentBuilder
import org.utbot.summary.name.SimpleNameBuilder
import java.io.File
Expand All @@ -37,7 +37,7 @@ import org.utbot.fuzzer.FuzzedValue
import org.utbot.fuzzer.UtFuzzedExecution
import org.utbot.summary.fuzzer.names.MethodBasedNameSuggester
import org.utbot.summary.fuzzer.names.ModelBasedNameSuggester
import org.utbot.summary.comment.CustomJavaDocCommentBuilder
import org.utbot.summary.comment.customtags.symbolic.CustomJavaDocCommentBuilder
import soot.SootMethod

private val logger = KotlinLogging.logger {}
Expand Down Expand Up @@ -241,6 +241,7 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe

utExecution.testMethodName = testMethodName?.testName
utExecution.displayName = testMethodName?.displayName
utExecution.summary = testMethodName?.javaDoc

when (utExecution.result) {
is UtConcreteExecutionFailure -> unsuccessfulFuzzerExecutions.add(utExecution)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.utbot.summary.comment.classic.fuzzer

import org.utbot.framework.plugin.api.DocPreTagStatement
import org.utbot.framework.plugin.api.DocStatement
import org.utbot.framework.plugin.api.UtExecutionResult
import org.utbot.fuzzer.FuzzedMethodDescription
import org.utbot.fuzzer.FuzzedValue

// TODO: https://github.com/UnitTestBot/UTBotJava/issues/1127
class SimpleCommentForTestProducedByFuzzerBuilder(
description: FuzzedMethodDescription,
values: List<FuzzedValue>,
result: UtExecutionResult?
) {
fun buildDocStatements(): List<DocStatement> {
return listOf<DocStatement>(DocPreTagStatement(emptyList()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.utbot.framework.plugin.api.exceptionOrNull
import org.utbot.summary.AbstractTextBuilder
import org.utbot.summary.SummarySentenceConstants.CARRIAGE_RETURN
import org.utbot.summary.ast.JimpleToASTMap
import org.utbot.summary.comment.customtags.getMethodReference
import org.utbot.summary.tag.BasicTypeTag
import org.utbot.summary.tag.CallOrderTag
import org.utbot.summary.tag.StatementTag
Expand Down Expand Up @@ -356,45 +357,6 @@ open class SimpleCommentBuilder(
)
}

/**
* Returns a reference to the invoked method. IDE can't resolve references to private methods in comments,
* so we add @link tag only if the invoked method is not private.
*
* It looks like {@link packageName.className#methodName(type1, type2)}.
*
* In case when an enclosing class in nested, we need to replace '$' with '.'
* to render the reference.
*/
fun getMethodReference(
className: String,
methodName: String,
methodParameterTypes: List<Type>,
isPrivate: Boolean
): String {
val prettyClassName: String = className.replace("$", ".")

val text = if (methodParameterTypes.isEmpty()) {
"$prettyClassName#$methodName()"
} else {
val methodParametersAsString = methodParameterTypes.joinToString(",")
"$prettyClassName#$methodName($methodParametersAsString)"
}

return if (isPrivate) {
text
} else {
"{@link $text}"
}
}

/**
* Returns a reference to the class.
* Replaces '$' with '.' in case a class is nested.
*/
fun getClassReference(fullClasName: String): String {
return "{@link ${fullClasName.replace("$", ".")}}"
}

protected fun buildIterationsBlock(
iterations: List<StatementTag>,
activatedStep: Step,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package org.utbot.summary.comment
package org.utbot.summary.comment.cluster

import com.github.javaparser.ast.stmt.CatchClause
import com.github.javaparser.ast.stmt.ForStmt
import org.utbot.framework.plugin.api.DocPreTagStatement
import org.utbot.framework.plugin.api.DocRegularStmt
import org.utbot.framework.plugin.api.DocStatement
import org.utbot.summary.SummarySentenceConstants.CARRIAGE_RETURN
import org.utbot.summary.ast.JimpleToASTMap
import org.utbot.summary.comment.*
import org.utbot.summary.comment.customtags.getMethodReference
import org.utbot.summary.tag.BasicTypeTag
import org.utbot.summary.tag.CallOrderTag
import org.utbot.summary.tag.StatementTag
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package org.utbot.summary.comment.customtags.symbolic

import org.utbot.framework.plugin.api.DocRegularStmt
import org.utbot.summary.comment.customtags.fuzzer.CommentWithCustomTagForTestProducedByFuzzer

/**
* Provides a list of supported custom JavaDoc tags.
*/
class CustomJavaDocTagProvider {
// The tags' order is important because plugin builds final JavaDoc comment according to it.
fun getPluginCustomTags(): List<CustomJavaDocTag> =
listOf(
CustomJavaDocTag.ClassUnderTest,
CustomJavaDocTag.MethodUnderTest,
CustomJavaDocTag.ExpectedResult,
CustomJavaDocTag.ActualResult,
CustomJavaDocTag.Executes,
CustomJavaDocTag.Invokes,
CustomJavaDocTag.Iterates,
CustomJavaDocTag.SwitchCase,
CustomJavaDocTag.Recursion,
CustomJavaDocTag.ReturnsFrom,
CustomJavaDocTag.CaughtException,
CustomJavaDocTag.ThrowsException,
)
}

sealed class CustomJavaDocTag(
val name: String,
val message: String,
private val valueRetriever: (CustomJavaDocComment) -> Any,
private val valueRetrieverFuzzer: ((CommentWithCustomTagForTestProducedByFuzzer) -> Any)? // TODO: remove after refactoring
) {
object ClassUnderTest :
CustomJavaDocTag(
"utbot.classUnderTest",
"Class under test",
CustomJavaDocComment::classUnderTest,
CommentWithCustomTagForTestProducedByFuzzer::classUnderTest
)

object MethodUnderTest :
CustomJavaDocTag(
"utbot.methodUnderTest",
"Method under test",
CustomJavaDocComment::methodUnderTest,
CommentWithCustomTagForTestProducedByFuzzer::methodUnderTest
)

object ExpectedResult :
CustomJavaDocTag("utbot.expectedResult", "Expected result", CustomJavaDocComment::expectedResult, null)

object ActualResult :
CustomJavaDocTag("utbot.actualResult", "Actual result", CustomJavaDocComment::actualResult, null)

object Executes :
CustomJavaDocTag("utbot.executesCondition", "Executes condition", CustomJavaDocComment::executesCondition, null)

object Invokes : CustomJavaDocTag("utbot.invokes", "Invokes", CustomJavaDocComment::invokes, null)
object Iterates : CustomJavaDocTag("utbot.iterates", "Iterates", CustomJavaDocComment::iterates, null)
object SwitchCase :
CustomJavaDocTag("utbot.activatesSwitch", "Activates switch", CustomJavaDocComment::switchCase, null)

object Recursion :
CustomJavaDocTag("utbot.triggersRecursion", "Triggers recursion ", CustomJavaDocComment::recursion, null)

object ReturnsFrom : CustomJavaDocTag("utbot.returnsFrom", "Returns from", CustomJavaDocComment::returnsFrom, null)
object CaughtException :
CustomJavaDocTag("utbot.caughtException", "Caught exception", CustomJavaDocComment::caughtException, null)

object ThrowsException :
CustomJavaDocTag("utbot.throwsException", "Throws exception", CustomJavaDocComment::throwsException, null)

fun generateDocStatement(comment: CustomJavaDocComment): DocRegularStmt? =
when (val value = valueRetriever.invoke(comment)) {
is String -> value.takeIf { it.isNotEmpty() }?.let {
DocRegularStmt("@$name $value\n")
}
is List<*> -> value.takeIf { it.isNotEmpty() }?.let {
val valueToString = value.joinToString(separator = "\n", postfix = "\n") { "@$name $it" }

DocRegularStmt(valueToString)
}
else -> null
}

// TODO: could be universal with the function above after creation of hierarchy data classes related to the comments
fun generateDocStatementForTestProducedByFuzzer(comment: CommentWithCustomTagForTestProducedByFuzzer): DocRegularStmt? {
if (valueRetrieverFuzzer != null) { //TODO: it required only when we have two different retrievers
return when (val value = valueRetrieverFuzzer!!.invoke(comment)) { // TODO: unsafe !! - resolve
is String -> value.takeIf { it.isNotEmpty() }?.let {
DocRegularStmt("@$name $value\n")
}

is List<*> -> value.takeIf { it.isNotEmpty() }?.let {
val valueToString = value.joinToString(separator = ",\n", postfix = "\n")

DocRegularStmt("@$name $valueToString")
}

else -> null
}
}
return null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.utbot.summary.comment.customtags

import org.utbot.framework.plugin.api.ClassId
import soot.Type

/**
* Returns a reference to the invoked method. IDE can't resolve references to private methods in comments,
* so we add @link tag only if the invoked method is not private.
*
* It looks like {@link packageName.className#methodName(type1, type2)}.
*
* In case when an enclosing class in nested, we need to replace '$' with '.'
* to render the reference.
*/
fun getMethodReference(
className: String,
methodName: String,
methodParameterTypes: List<Type>,
isPrivate: Boolean
): String {
val prettyClassName: String = className.replace("$", ".")

val text = if (methodParameterTypes.isEmpty()) {
"$prettyClassName#$methodName()"
} else {
val methodParametersAsString = methodParameterTypes.joinToString(",")
"$prettyClassName#$methodName($methodParametersAsString)"
}

return if (isPrivate) {
text
} else {
"{@link $text}"
}
}

/**
* Returns a reference to the class.
* Replaces '$' with '.' in case a class is nested.
*/
fun getClassReference(fullClassName: String): String {
return "{@link ${fullClassName.replace("$", ".")}}"
}

/**
* Returns a reference to the invoked method.
*
* It looks like {@link packageName.className#methodName(type1, type2)}.
*
* In case when an enclosing class in nested, we need to replace '$' with '.'
* to render the reference.
*/
fun getMethodReferenceForFuzzingTest(className: String, methodName: String, methodParameterTypes: List<ClassId>, isPrivate: Boolean): String {
val prettyClassName: String = className.replace("$", ".")

val text = if (methodParameterTypes.isEmpty()) {
"$prettyClassName#$methodName()"
} else {
val methodParametersAsString = methodParameterTypes.joinToString(",") { it.canonicalName }
"$prettyClassName#$methodName($methodParametersAsString)"
}

return if (isPrivate) {
text
} else {
"{@link $text}"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.utbot.summary.comment.customtags.fuzzer

import org.utbot.summary.comment.EMPTY_STRING

/**
* Represents a set of plugin's custom JavaDoc tags.
*/
data class CommentWithCustomTagForTestProducedByFuzzer(
val classUnderTest: String = EMPTY_STRING,
val methodUnderTest: String = EMPTY_STRING,
val expectedResult: String = EMPTY_STRING,
val actualResult: String = EMPTY_STRING,
var returnsFrom: String = EMPTY_STRING,
var throwsException: String = EMPTY_STRING
)
Loading