@@ -16,13 +16,20 @@ import org.utbot.summary.UtSummarySettings.GENERATE_NAMES
1616import org.utbot.summary.analysis.ExecutionStructureAnalysis
1717import org.utbot.summary.ast.JimpleToASTMap
1818import org.utbot.summary.ast.SourceCodeParser
19- import org.utbot.summary.comment.SimpleClusterCommentBuilder
19+ import org.utbot.summary.comment.SymbolicExecutionClusterCommentBuilder
2020import org.utbot.summary.comment.SimpleCommentBuilder
2121import org.utbot.summary.name.SimpleNameBuilder
2222import java.io.File
2323import java.nio.file.Path
2424import java.nio.file.Paths
2525import mu.KotlinLogging
26+ import org.utbot.framework.plugin.api.UtConcreteExecutionFailure
27+ import org.utbot.framework.plugin.api.UtExecutionSuccess
28+ import org.utbot.framework.plugin.api.UtExplicitlyThrownException
29+ import org.utbot.framework.plugin.api.UtImplicitlyThrownException
30+ import org.utbot.framework.plugin.api.UtOverflowFailure
31+ import org.utbot.framework.plugin.api.UtSandboxFailure
32+ import org.utbot.framework.plugin.api.UtTimeoutException
2633import org.utbot.fuzzer.FuzzedMethodDescription
2734import org.utbot.fuzzer.FuzzedValue
2835import org.utbot.fuzzer.UtFuzzedExecution
@@ -40,7 +47,7 @@ fun UtMethodTestSet.summarize(sourceFile: File?, searchDirectory: Path = Paths.g
4047 makeDiverseExecutions(this )
4148 val invokeDescriptions = invokeDescriptions(this , searchDirectory)
4249 // every cluster has summary and list of executions
43- val executionClusters = Summarization (sourceFile, invokeDescriptions).summary (this )
50+ val executionClusters = Summarization (sourceFile, invokeDescriptions).fillSummaries (this )
4451 val updatedExecutions = executionClusters.flatMap { it.executions }
4552 var pos = 0
4653 val clustersInfo = executionClusters.map {
@@ -49,7 +56,10 @@ fun UtMethodTestSet.summarize(sourceFile: File?, searchDirectory: Path = Paths.g
4956 pos + = clusterSize
5057 it.clusterInfo to indices
5158 }
52- this .copy(executions = updatedExecutions, clustersInfo = clustersInfo) // TODO: looks weird and don't create the real copy
59+ this .copy(
60+ executions = updatedExecutions,
61+ clustersInfo = clustersInfo
62+ ) // TODO: looks weird and don't create the real copy
5363 } catch (e: Throwable ) {
5464 logger.info(e) { " Summary generation error" }
5565 this
@@ -64,7 +74,7 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
6474 private val tagGenerator = TagGenerator ()
6575 private val jimpleBodyAnalysis = ExecutionStructureAnalysis ()
6676
67- fun summary (testSet : UtMethodTestSet ): List <UtExecutionCluster > {
77+ fun fillSummaries (testSet : UtMethodTestSet ): List <UtExecutionCluster > {
6878 val namesCounter = mutableMapOf<String , Int >()
6979
7080 if (testSet.executions.isEmpty()) {
@@ -83,28 +93,61 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
8393
8494 // handles tests produced by fuzzing
8595 val executionsProducedByFuzzer = testSet.executions.filterIsInstance<UtFuzzedExecution >()
96+ val successfulFuzzerExecutions = mutableListOf<UtFuzzedExecution >()
97+ val unsuccessfulFuzzerExecutions = mutableListOf<UtFuzzedExecution >()
8698
8799 if (executionsProducedByFuzzer.isNotEmpty()) {
88100 executionsProducedByFuzzer.forEach { utExecution ->
89101
90102 val nameSuggester = sequenceOf(ModelBasedNameSuggester (), MethodBasedNameSuggester ())
91103 val testMethodName = try {
92- nameSuggester.flatMap { it.suggest(utExecution.fuzzedMethodDescription as FuzzedMethodDescription , utExecution.fuzzingValues as List <FuzzedValue >, utExecution.result) }.firstOrNull()
104+ nameSuggester.flatMap {
105+ it.suggest(
106+ utExecution.fuzzedMethodDescription as FuzzedMethodDescription ,
107+ utExecution.fuzzingValues as List <FuzzedValue >,
108+ utExecution.result
109+ )
110+ }.firstOrNull()
93111 } catch (t: Throwable ) {
94112 logger.error(t) { " Cannot create suggested test name for $utExecution " } // TODO: add better explanation or default behavoiur
95113 null
96114 }
97115
98116 utExecution.testMethodName = testMethodName?.testName
99- utExecution.displayName = testMethodName?.displayName
117+ utExecution.displayName = testMethodName?.displayName
118+
119+ when (utExecution.result) {
120+ is UtConcreteExecutionFailure -> unsuccessfulFuzzerExecutions.add(utExecution)
121+ is UtExplicitlyThrownException -> unsuccessfulFuzzerExecutions.add(utExecution)
122+ is UtImplicitlyThrownException -> unsuccessfulFuzzerExecutions.add(utExecution)
123+ is UtOverflowFailure -> unsuccessfulFuzzerExecutions.add(utExecution)
124+ is UtSandboxFailure -> unsuccessfulFuzzerExecutions.add(utExecution)
125+ is UtTimeoutException -> unsuccessfulFuzzerExecutions.add(utExecution)
126+ is UtExecutionSuccess -> successfulFuzzerExecutions.add(utExecution)
127+ }
100128 }
101129
102- clustersToReturn.add(
103- UtExecutionCluster (
104- UtClusterInfo (), // TODO: add something https://github.com/UnitTestBot/UTBotJava/issues/430
105- executionsProducedByFuzzer
130+ if (successfulFuzzerExecutions.isNotEmpty()) {
131+ val clusterHeader = buildFuzzerClusterHeaderForSuccessfulExecutions(testSet)
132+
133+ clustersToReturn.add(
134+ UtExecutionCluster (
135+ UtClusterInfo (clusterHeader, null ),
136+ successfulFuzzerExecutions
137+ )
106138 )
107- )
139+ }
140+
141+ if (unsuccessfulFuzzerExecutions.isNotEmpty()) {
142+ val clusterHeader = buildFuzzerClusterHeaderForUnsuccessfulExecutions(testSet)
143+
144+ clustersToReturn.add(
145+ UtExecutionCluster (
146+ UtClusterInfo (clusterHeader, null ),
147+ unsuccessfulFuzzerExecutions
148+ )
149+ )
150+ }
108151 }
109152
110153 // handles tests produced by symbolic engine, but with empty paths
@@ -113,14 +156,14 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
113156 if (executionsWithEmptyPaths.isNotEmpty()) {
114157 executionsWithEmptyPaths.forEach {
115158 logger.info {
116- " Test is created by Symbolic Engine. The path for test ${it.testMethodName} " +
159+ " Test is created by Symbolic Execution Engine. The path for test ${it.testMethodName} " +
117160 " for method ${testSet.method.clazz.qualifiedName} is empty and summaries could not be generated."
118161 }
119162 }
120163
121164 clustersToReturn.add(
122165 UtExecutionCluster (
123- UtClusterInfo (), // TODO: https://github.com/UnitTestBot/UTBotJava/issues/430
166+ UtClusterInfo (),
124167 executionsWithEmptyPaths
125168 )
126169 )
@@ -135,13 +178,13 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
135178 jimpleBodyAnalysis.traceStructuralAnalysis(jimpleBody, clusteredTags, methodUnderTest, invokeDescriptions)
136179 val numberOfSuccessfulClusters = clusteredTags.filter { it.isSuccessful }.size
137180 for (clusterTraceTags in clusteredTags) {
138- val clusterHeader = clusterTraceTags.summary .takeIf { GENERATE_CLUSTER_COMMENTS }
181+ val clusterHeader = clusterTraceTags.clusterHeader .takeIf { GENERATE_CLUSTER_COMMENTS }
139182 val clusterContent = if (
140183 GENERATE_CLUSTER_COMMENTS && clusterTraceTags.isSuccessful // add only for successful executions
141184 && numberOfSuccessfulClusters > 1 // there is more than one successful execution
142185 && clusterTraceTags.traceTags.size > 1 // add if there is more than 1 execution
143186 ) {
144- SimpleClusterCommentBuilder (clusterTraceTags.commonStepsTraceTag, sootToAST)
187+ SymbolicExecutionClusterCommentBuilder (clusterTraceTags.commonStepsTraceTag, sootToAST)
145188 .buildString(methodUnderTest)
146189 .takeIf { it.isNotBlank() }
147190 ?.let {
@@ -204,6 +247,20 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
204247 return listOf (UtExecutionCluster (UtClusterInfo (), testSet.executions))
205248 }
206249
250+ private fun buildFuzzerClusterHeaderForSuccessfulExecutions (testSet : UtMethodTestSet ): String {
251+ val commentPrefix = " FUZZER:"
252+ val commentPostfix = " for method ${testSet.method.humanReadableName} "
253+
254+ return " $commentPrefix ${ExecutionGroup .SUCCESSFUL_EXECUTIONS .displayName} $commentPostfix "
255+ }
256+
257+ private fun buildFuzzerClusterHeaderForUnsuccessfulExecutions (testSet : UtMethodTestSet ): String {
258+ val commentPrefix = " FUZZER:"
259+ val commentPostfix = " for method ${testSet.method.humanReadableName} "
260+
261+ return " $commentPrefix ${ExecutionGroup .EXPLICITLY_THROWN_UNCHECKED_EXCEPTIONS } $commentPostfix "
262+ }
263+
207264 private fun prepareTestSetForByteCodeAnalysis (testSet : UtMethodTestSet ): UtMethodTestSet {
208265 val executions =
209266 testSet.executions.filterIsInstance<UtSymbolicExecution >().filter { it.path.isNotEmpty() }
@@ -278,7 +335,8 @@ private fun makeDiverseExecutions(testSet: UtMethodTestSet) {
278335}
279336
280337private fun invokeDescriptions (testSet : UtMethodTestSet , searchDirectory : Path ): List <InvokeDescription > {
281- val sootInvokes = testSet.executions.filterIsInstance<UtSymbolicExecution >().flatMap { it.path.invokeJimpleMethods() }.toSet()
338+ val sootInvokes =
339+ testSet.executions.filterIsInstance<UtSymbolicExecution >().flatMap { it.path.invokeJimpleMethods() }.toSet()
282340 return sootInvokes
283341 // TODO(SAT-1170)
284342 .filterNot { " \$ lambda" in it.declaringClass.name }
0 commit comments