Skip to content

Commit 196dc2a

Browse files
authored
Add support for Artificial Errors in Summaries #1739 (#1785)
Support Artificial Errors in summaries
1 parent a5c0df4 commit 196dc2a

File tree

14 files changed

+144
-14
lines changed

14 files changed

+144
-14
lines changed

utbot-framework/src/main/kotlin/org/utbot/engine/ArtificialErrors.kt renamed to utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/ArtificialErrors.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.utbot.engine
1+
package org.utbot.framework.plugin.api
22

33
/**
44
* Represents an error that may be detected or not
@@ -15,4 +15,9 @@ sealed class ArtificialError(message: String): Error(message)
1515
*
1616
* See [TraversalContext.intOverflowCheck] for more details.
1717
*/
18-
class OverflowDetectionError(message: String): ArtificialError(message)
18+
class OverflowDetectionError(message: String): ArtificialError(message)
19+
20+
fun ArtificialError.getPrettyName(): String =
21+
when (this) {
22+
is OverflowDetectionError -> "Overflow"
23+
}

utbot-framework-test/src/test/kotlin/org/utbot/examples/math/OverflowAsErrorTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package org.utbot.examples.math
22

33
import org.junit.jupiter.api.Disabled
44
import org.junit.jupiter.api.Test
5-
import org.utbot.engine.OverflowDetectionError
5+
import org.utbot.framework.plugin.api.OverflowDetectionError
66
import org.utbot.examples.algorithms.Sort
77
import org.utbot.framework.plugin.api.CodegenLanguage
88
import org.utbot.testcheckers.eq

utbot-framework/src/main/kotlin/org/utbot/engine/Resolver.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ import kotlin.math.max
9090
import kotlin.math.min
9191
import kotlinx.collections.immutable.persistentListOf
9292
import kotlinx.collections.immutable.persistentSetOf
93+
import org.utbot.framework.plugin.api.OverflowDetectionError
9394
import org.utbot.engine.types.CLASS_REF_CLASSNAME
9495
import org.utbot.engine.types.CLASS_REF_CLASS_ID
9596
import org.utbot.engine.types.CLASS_REF_NUM_DIMENSIONS_DESCRIPTOR

utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import kotlinx.collections.immutable.toPersistentList
88
import kotlinx.collections.immutable.toPersistentMap
99
import kotlinx.collections.immutable.toPersistentSet
1010
import mu.KotlinLogging
11+
import org.utbot.framework.plugin.api.ArtificialError
12+
import org.utbot.framework.plugin.api.OverflowDetectionError
1113
import org.utbot.common.WorkaroundReason.HACK
1214
import org.utbot.framework.UtSettings.ignoreStaticsFromTrustedLibraries
1315
import org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMethodConstructor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package org.utbot.framework.codegen.tree
33
import org.utbot.common.WorkaroundReason
44
import org.utbot.common.isStatic
55
import org.utbot.common.workaround
6-
import org.utbot.engine.ArtificialError
76
import org.utbot.framework.UtSettings
7+
import org.utbot.framework.plugin.api.ArtificialError
88
import org.utbot.framework.assemble.assemble
99
import org.utbot.framework.codegen.domain.ForceStaticMocking
1010
import org.utbot.framework.codegen.domain.ParametrizedTestSource

utbot-framework/src/main/kotlin/org/utbot/framework/util/SootUtils.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.utbot.framework.util
22

33
import org.utbot.common.FileUtil
44
import org.utbot.engine.jimpleBody
5-
import org.utbot.engine.overrides.collections.UtLinkedList
65
import org.utbot.engine.pureJavaSignature
76
import org.utbot.framework.UtSettings
87
import org.utbot.framework.plugin.api.ExecutableId
@@ -208,7 +207,7 @@ private val classesToLoad = arrayOf(
208207
org.utbot.engine.overrides.stream.IntStream::class,
209208
org.utbot.engine.overrides.stream.LongStream::class,
210209
org.utbot.engine.overrides.stream.DoubleStream::class,
211-
org.utbot.engine.OverflowDetectionError::class,
210+
org.utbot.framework.plugin.api.OverflowDetectionError::class,
212211
).map { it.java }.toTypedArray()
213212

214213
private const val UTBOT_PACKAGE_PREFIX = "org.utbot"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package math
2+
3+
import examples.CustomJavaDocTagsEnabler
4+
import examples.SummaryTestCaseGeneratorTest
5+
import org.junit.jupiter.api.Test
6+
import org.junit.jupiter.api.extension.ExtendWith
7+
import org.utbot.examples.math.OverflowExamples
8+
import org.utbot.framework.plugin.api.MockStrategyApi
9+
import org.utbot.testcheckers.withTreatingOverflowAsError
10+
import org.utbot.testing.DoNotCalculate
11+
12+
@ExtendWith(CustomJavaDocTagsEnabler::class)
13+
class SummaryOverflowExamples : SummaryTestCaseGeneratorTest(
14+
OverflowExamples::class
15+
) {
16+
@Test
17+
fun testShortMulOverflow() {
18+
val summary1 = "@utbot.classUnderTest {@link OverflowExamples}\n" +
19+
"@utbot.methodUnderTest {@link org.utbot.examples.math.OverflowExamples#shortMulOverflow(short,short)}\n" +
20+
"@utbot.returnsFrom {@code return (short) (x * y);}\n"
21+
val summary2 = "@utbot.classUnderTest {@link OverflowExamples}\n" +
22+
"@utbot.methodUnderTest {@link org.utbot.examples.math.OverflowExamples#shortMulOverflow(short,short)}\n" +
23+
"@utbot.detectsSuspiciousBehavior in: return (short) (x * y);\n"
24+
25+
val methodName1 = "testShortMulOverflow_ReturnXy"
26+
val methodName2 = "testShortMulOverflow_DetectOverflow"
27+
28+
val displayName1 = "-> return (short) (x * y)"
29+
val displayName2 = "return (short) (x * y) : True -> DetectOverflow"
30+
31+
val summaryKeys = listOf(
32+
summary1,
33+
summary2
34+
)
35+
36+
val displayNames = listOf(
37+
displayName1,
38+
displayName2
39+
)
40+
41+
val methodNames = listOf(
42+
methodName1,
43+
methodName2
44+
)
45+
46+
val method = OverflowExamples::shortMulOverflow
47+
val mockStrategy = MockStrategyApi.NO_MOCKS
48+
val coverage = DoNotCalculate
49+
50+
withTreatingOverflowAsError {
51+
summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames)
52+
}
53+
}
54+
}

utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleCommentBuilder.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.github.javaparser.ast.stmt.IfStmt
77
import com.github.javaparser.ast.stmt.Statement
88
import com.github.javaparser.ast.stmt.SwitchStmt
99
import com.github.javaparser.ast.stmt.ThrowStmt
10+
import org.utbot.framework.plugin.api.ArtificialError
1011
import org.utbot.framework.plugin.api.InstrumentedProcessDeathException
1112
import org.utbot.framework.plugin.api.DocPreTagStatement
1213
import org.utbot.framework.plugin.api.DocRegularStmt
@@ -67,7 +68,11 @@ open class SimpleCommentBuilder(
6768
traceTag.result.exceptionOrNull()?.let {
6869
val exceptionName = it.javaClass.simpleName
6970
val reason = findExceptionReason(currentMethod, it)
70-
root.exceptionThrow = "$exceptionName $reason"
71+
72+
when (it) {
73+
is ArtificialError -> root.detectedError = reason
74+
else -> root.exceptionThrow = "$exceptionName $reason"
75+
}
7176
}
7277
}
7378

utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleSentenceBlock.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class SimpleSentenceBlock(val stringTemplates: StringsTemplatesInterface) {
1919
var notExecutedIterations: List<IterationDescription>? = null
2020
var recursion: Pair<String, SimpleSentenceBlock>? = null
2121
var exceptionThrow: String? = null
22+
var detectedError: String? = null
2223
var nextBlock: SimpleSentenceBlock? = null
2324

2425
val stmtTexts = mutableListOf<StmtDescription>()
@@ -122,6 +123,15 @@ class SimpleSentenceBlock(val stringTemplates: StringsTemplatesInterface) {
122123
result += NEW_LINE
123124
}
124125

126+
detectedError?.let {
127+
if (restartSentence) {
128+
result += stringTemplates.sentenceBeginning + " "
129+
restartSentence = false
130+
}
131+
result += stringTemplates.suspiciousBehaviorDetectedSentence.format(it)
132+
result += NEW_LINE
133+
}
134+
125135
return result
126136
}
127137

@@ -238,6 +248,16 @@ class SimpleSentenceBlock(val stringTemplates: StringsTemplatesInterface) {
238248
docStmts += DocRegularStmt(NEW_LINE)
239249
}
240250

251+
detectedError?.let {
252+
docStmts += DocRegularStmt(NEW_LINE)
253+
if (restartSentence) {
254+
docStmts += DocRegularStmt(stringTemplates.sentenceBeginning + " ")
255+
restartSentence = false
256+
}
257+
docStmts += DocRegularStmt(stringTemplates.suspiciousBehaviorDetectedSentence.format(it))
258+
docStmts += DocRegularStmt(NEW_LINE)
259+
}
260+
241261
return docStmts
242262
}
243263

@@ -323,6 +343,7 @@ class SimpleSentenceBlock(val stringTemplates: StringsTemplatesInterface) {
323343
if (nextBlock?.isEmpty() == false) return false
324344
if (notExecutedIterations.isNullOrEmpty().not()) return false
325345
exceptionThrow?.let { return false }
346+
detectedError?.let { return false }
326347
if (invokeSentenceBlock != null) return false
327348
return true
328349
}
@@ -478,6 +499,7 @@ interface StringsTemplatesInterface {
478499
val noIteration: String
479500
val codeSentence: String
480501
val throwSentence: String
502+
val suspiciousBehaviorDetectedSentence: String
481503

482504
val conditionLine: String
483505
val returnLine: String
@@ -498,6 +520,7 @@ open class StringsTemplatesSingular : StringsTemplatesInterface {
498520
override val noIteration: String = "does not iterate"
499521
override val codeSentence: String = "$OPEN_BRACKET$AT_CODE %s$CLOSE_BRACKET"
500522
override val throwSentence: String = "throws %s"
523+
override val suspiciousBehaviorDetectedSentence: String = "detects suspicious behavior %s"
501524

502525
//used in Squashing
503526
override val conditionLine: String = "executes conditions:$NEW_LINE"
@@ -519,6 +542,7 @@ class StringsTemplatesPlural : StringsTemplatesSingular() {
519542
override val noIteration: String = "does not iterate"
520543
override val codeSentence: String = "$OPEN_BRACKET$AT_CODE %s$CLOSE_BRACKET"
521544
override val throwSentence: String = "throw %s"
545+
override val suspiciousBehaviorDetectedSentence: String = "detect suspicious behavior %s"
522546

523547
//used in Squashing
524548
override val conditionLine: String = "execute conditions:$NEW_LINE"

utbot-summary/src/main/kotlin/org/utbot/summary/comment/customtags/CustomJavaDocTagProvider.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class CustomJavaDocTagProvider {
2424
CustomJavaDocTag.ReturnsFrom,
2525
CustomJavaDocTag.CaughtException,
2626
CustomJavaDocTag.ThrowsException,
27+
CustomJavaDocTag.DetectsSuspiciousBehavior,
2728
)
2829
}
2930

@@ -73,6 +74,9 @@ sealed class CustomJavaDocTag(
7374
object ThrowsException :
7475
CustomJavaDocTag("utbot.throwsException", "Throws exception", CustomJavaDocComment::throwsException, null)
7576

77+
object DetectsSuspiciousBehavior :
78+
CustomJavaDocTag("utbot.detectsSuspiciousBehavior", "Detects suspicious behavior", CustomJavaDocComment::detectsSuspiciousBehavior, null)
79+
7680
fun generateDocStatement(comment: CustomJavaDocComment): DocRegularStmt? =
7781
when (val value = valueRetriever.invoke(comment)) {
7882
is String -> value.takeIf { it.isNotEmpty() }?.let {

0 commit comments

Comments
 (0)